]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
remove r_glsl_saturation_redcompensate, as it's considered a hack and can be done...
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30
31 mempool_t *r_main_mempool;
32 rtexturepool_t *r_main_texturepool;
33
34 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
35
36 static qboolean r_loadnormalmap;
37 static qboolean r_loadgloss;
38 qboolean r_loadfog;
39 static qboolean r_loaddds;
40 static qboolean r_savedds;
41
42 //
43 // screen size info
44 //
45 r_refdef_t r_refdef;
46
47 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
48 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
49 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
50 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
51 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)"};
52 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
53 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
54 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
55
56 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
57 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"};
58 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
59 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)"};
60 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
61
62 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"};
63 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
64 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
65 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
66 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
67 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
68 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)"};
69 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
70 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
71 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"};
72 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"};
73 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
74 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"};
75 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"};
76 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"};
77 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
78 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
79 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
80 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
81 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
82 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
83 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
84 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)"};
85 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)"};
86 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
87 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
88 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
89 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
90
91 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
92 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
93 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
94
95 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
96 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
97 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
98 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
99 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
100 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
101 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
102 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
103 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
104 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
105 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
106 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
107 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
108 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
109 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
110 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
111 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
112 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
113 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
114
115 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
116 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
117 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
118 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
119 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
120 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
121 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
122 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
123
124 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
125 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
126
127 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
128 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
129 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
130 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
131 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
132
133 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
134 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
135 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
136
137 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
138 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
139 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
140 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
141 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
142 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
143 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
144 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
145 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
146
147 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
148 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
149 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
150 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
151 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
152 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
153
154 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
155 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
156 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
157 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
158
159 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
160 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
161 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
162 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
163 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
164 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
165 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
166
167 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
168 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
169 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
170 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)"};
171
172 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"};
173
174 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"};
175
176 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
177
178 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
179 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
180 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"};
181 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
182 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
183 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
184 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
185 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)"};
186
187 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
188
189 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)"};
190
191 extern cvar_t v_glslgamma;
192
193 extern qboolean v_flipped_state;
194
195 static struct r_bloomstate_s
196 {
197         qboolean enabled;
198         qboolean hdr;
199
200         int bloomwidth, bloomheight;
201
202         int screentexturewidth, screentextureheight;
203         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
204
205         int bloomtexturewidth, bloomtextureheight;
206         rtexture_t *texture_bloom;
207
208         // arrays for rendering the screen passes
209         float screentexcoord2f[8];
210         float bloomtexcoord2f[8];
211         float offsettexcoord2f[8];
212
213         r_viewport_t viewport;
214 }
215 r_bloomstate;
216
217 r_waterstate_t r_waterstate;
218
219 /// shadow volume bsp struct with automatically growing nodes buffer
220 svbsp_t r_svbsp;
221
222 rtexture_t *r_texture_blanknormalmap;
223 rtexture_t *r_texture_white;
224 rtexture_t *r_texture_grey128;
225 rtexture_t *r_texture_black;
226 rtexture_t *r_texture_notexture;
227 rtexture_t *r_texture_whitecube;
228 rtexture_t *r_texture_normalizationcube;
229 rtexture_t *r_texture_fogattenuation;
230 rtexture_t *r_texture_fogheighttexture;
231 rtexture_t *r_texture_gammaramps;
232 unsigned int r_texture_gammaramps_serial;
233 //rtexture_t *r_texture_fogintensity;
234 rtexture_t *r_texture_reflectcube;
235
236 // TODO: hash lookups?
237 typedef struct cubemapinfo_s
238 {
239         char basename[64];
240         rtexture_t *texture;
241 }
242 cubemapinfo_t;
243
244 int r_texture_numcubemaps;
245 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
246
247 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
248 unsigned int r_numqueries;
249 unsigned int r_maxqueries;
250
251 typedef struct r_qwskincache_s
252 {
253         char name[MAX_QPATH];
254         skinframe_t *skinframe;
255 }
256 r_qwskincache_t;
257
258 static r_qwskincache_t *r_qwskincache;
259 static int r_qwskincache_size;
260
261 /// vertex coordinates for a quad that covers the screen exactly
262 const float r_screenvertex3f[12] =
263 {
264         0, 0, 0,
265         1, 0, 0,
266         1, 1, 0,
267         0, 1, 0
268 };
269
270 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
271 {
272         int i;
273         for (i = 0;i < verts;i++)
274         {
275                 out[0] = in[0] * r;
276                 out[1] = in[1] * g;
277                 out[2] = in[2] * b;
278                 out[3] = in[3];
279                 in += 4;
280                 out += 4;
281         }
282 }
283
284 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
285 {
286         int i;
287         for (i = 0;i < verts;i++)
288         {
289                 out[0] = r;
290                 out[1] = g;
291                 out[2] = b;
292                 out[3] = a;
293                 out += 4;
294         }
295 }
296
297 // FIXME: move this to client?
298 void FOG_clear(void)
299 {
300         if (gamemode == GAME_NEHAHRA)
301         {
302                 Cvar_Set("gl_fogenable", "0");
303                 Cvar_Set("gl_fogdensity", "0.2");
304                 Cvar_Set("gl_fogred", "0.3");
305                 Cvar_Set("gl_foggreen", "0.3");
306                 Cvar_Set("gl_fogblue", "0.3");
307         }
308         r_refdef.fog_density = 0;
309         r_refdef.fog_red = 0;
310         r_refdef.fog_green = 0;
311         r_refdef.fog_blue = 0;
312         r_refdef.fog_alpha = 1;
313         r_refdef.fog_start = 0;
314         r_refdef.fog_end = 16384;
315         r_refdef.fog_height = 1<<30;
316         r_refdef.fog_fadedepth = 128;
317         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
318 }
319
320 static void R_BuildBlankTextures(void)
321 {
322         unsigned char data[4];
323         data[2] = 128; // normal X
324         data[1] = 128; // normal Y
325         data[0] = 255; // normal Z
326         data[3] = 128; // height
327         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
328         data[0] = 255;
329         data[1] = 255;
330         data[2] = 255;
331         data[3] = 255;
332         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
333         data[0] = 128;
334         data[1] = 128;
335         data[2] = 128;
336         data[3] = 255;
337         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
338         data[0] = 0;
339         data[1] = 0;
340         data[2] = 0;
341         data[3] = 255;
342         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
343 }
344
345 static void R_BuildNoTexture(void)
346 {
347         int x, y;
348         unsigned char pix[16][16][4];
349         // this makes a light grey/dark grey checkerboard texture
350         for (y = 0;y < 16;y++)
351         {
352                 for (x = 0;x < 16;x++)
353                 {
354                         if ((y < 8) ^ (x < 8))
355                         {
356                                 pix[y][x][0] = 128;
357                                 pix[y][x][1] = 128;
358                                 pix[y][x][2] = 128;
359                                 pix[y][x][3] = 255;
360                         }
361                         else
362                         {
363                                 pix[y][x][0] = 64;
364                                 pix[y][x][1] = 64;
365                                 pix[y][x][2] = 64;
366                                 pix[y][x][3] = 255;
367                         }
368                 }
369         }
370         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
371 }
372
373 static void R_BuildWhiteCube(void)
374 {
375         unsigned char data[6*1*1*4];
376         memset(data, 255, sizeof(data));
377         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
378 }
379
380 static void R_BuildNormalizationCube(void)
381 {
382         int x, y, side;
383         vec3_t v;
384         vec_t s, t, intensity;
385 #define NORMSIZE 64
386         unsigned char *data;
387         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
388         for (side = 0;side < 6;side++)
389         {
390                 for (y = 0;y < NORMSIZE;y++)
391                 {
392                         for (x = 0;x < NORMSIZE;x++)
393                         {
394                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
395                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
396                                 switch(side)
397                                 {
398                                 default:
399                                 case 0:
400                                         v[0] = 1;
401                                         v[1] = -t;
402                                         v[2] = -s;
403                                         break;
404                                 case 1:
405                                         v[0] = -1;
406                                         v[1] = -t;
407                                         v[2] = s;
408                                         break;
409                                 case 2:
410                                         v[0] = s;
411                                         v[1] = 1;
412                                         v[2] = t;
413                                         break;
414                                 case 3:
415                                         v[0] = s;
416                                         v[1] = -1;
417                                         v[2] = -t;
418                                         break;
419                                 case 4:
420                                         v[0] = s;
421                                         v[1] = -t;
422                                         v[2] = 1;
423                                         break;
424                                 case 5:
425                                         v[0] = -s;
426                                         v[1] = -t;
427                                         v[2] = -1;
428                                         break;
429                                 }
430                                 intensity = 127.0f / sqrt(DotProduct(v, v));
431                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
432                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
433                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
434                                 data[((side*64+y)*64+x)*4+3] = 255;
435                         }
436                 }
437         }
438         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
439         Mem_Free(data);
440 }
441
442 static void R_BuildFogTexture(void)
443 {
444         int x, b;
445 #define FOGWIDTH 256
446         unsigned char data1[FOGWIDTH][4];
447         //unsigned char data2[FOGWIDTH][4];
448         double d, r, alpha;
449
450         r_refdef.fogmasktable_start = r_refdef.fog_start;
451         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
452         r_refdef.fogmasktable_range = r_refdef.fogrange;
453         r_refdef.fogmasktable_density = r_refdef.fog_density;
454
455         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
456         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
457         {
458                 d = (x * r - r_refdef.fogmasktable_start);
459                 if(developer_extra.integer)
460                         Con_DPrintf("%f ", d);
461                 d = max(0, d);
462                 if (r_fog_exp2.integer)
463                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
464                 else
465                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
466                 if(developer_extra.integer)
467                         Con_DPrintf(" : %f ", alpha);
468                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
469                 if(developer_extra.integer)
470                         Con_DPrintf(" = %f\n", alpha);
471                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
472         }
473
474         for (x = 0;x < FOGWIDTH;x++)
475         {
476                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
477                 data1[x][0] = b;
478                 data1[x][1] = b;
479                 data1[x][2] = b;
480                 data1[x][3] = 255;
481                 //data2[x][0] = 255 - b;
482                 //data2[x][1] = 255 - b;
483                 //data2[x][2] = 255 - b;
484                 //data2[x][3] = 255;
485         }
486         if (r_texture_fogattenuation)
487         {
488                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
489                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
490         }
491         else
492         {
493                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
494                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
495         }
496 }
497
498 static void R_BuildFogHeightTexture(void)
499 {
500         unsigned char *inpixels;
501         int size;
502         int x;
503         int y;
504         int j;
505         float c[4];
506         float f;
507         inpixels = NULL;
508         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
509         if (r_refdef.fogheighttexturename[0])
510                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
511         if (!inpixels)
512         {
513                 r_refdef.fog_height_tablesize = 0;
514                 if (r_texture_fogheighttexture)
515                         R_FreeTexture(r_texture_fogheighttexture);
516                 r_texture_fogheighttexture = NULL;
517                 if (r_refdef.fog_height_table2d)
518                         Mem_Free(r_refdef.fog_height_table2d);
519                 r_refdef.fog_height_table2d = NULL;
520                 if (r_refdef.fog_height_table1d)
521                         Mem_Free(r_refdef.fog_height_table1d);
522                 r_refdef.fog_height_table1d = NULL;
523                 return;
524         }
525         size = image_width;
526         r_refdef.fog_height_tablesize = size;
527         r_refdef.fog_height_table1d = Mem_Alloc(r_main_mempool, size * 4);
528         r_refdef.fog_height_table2d = Mem_Alloc(r_main_mempool, size * size * 4);
529         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
530         Mem_Free(inpixels);
531         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
532         // average fog color table accounting for every fog layer between a point
533         // and the camera.  (Note: attenuation is handled separately!)
534         for (y = 0;y < size;y++)
535         {
536                 for (x = 0;x < size;x++)
537                 {
538                         Vector4Clear(c);
539                         f = 0;
540                         if (x < y)
541                         {
542                                 for (j = x;j <= y;j++)
543                                 {
544                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
545                                         f++;
546                                 }
547                         }
548                         else
549                         {
550                                 for (j = x;j >= y;j--)
551                                 {
552                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
553                                         f++;
554                                 }
555                         }
556                         f = 1.0f / f;
557                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
558                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
559                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
560                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
561                 }
562         }
563         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
564 }
565
566 //=======================================================================================================================================================
567
568 static const char *builtinshaderstring =
569 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
570 "// written by Forest 'LordHavoc' Hale\n"
571 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
572 "\n"
573 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
574 "# define USEFOG\n"
575 "#endif\n"
576 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
577 "#define USELIGHTMAP\n"
578 "#endif\n"
579 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
580 "#define USEEYEVECTOR\n"
581 "#endif\n"
582 "\n"
583 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
584 "# extension GL_ARB_texture_rectangle : enable\n"
585 "#endif\n"
586 "\n"
587 "#ifdef USESHADOWMAP2D\n"
588 "# ifdef GL_EXT_gpu_shader4\n"
589 "#   extension GL_EXT_gpu_shader4 : enable\n"
590 "# endif\n"
591 "# ifdef GL_ARB_texture_gather\n"
592 "#   extension GL_ARB_texture_gather : enable\n"
593 "# else\n"
594 "#   ifdef GL_AMD_texture_texture4\n"
595 "#     extension GL_AMD_texture_texture4 : enable\n"
596 "#   endif\n"
597 "# endif\n"
598 "#endif\n"
599 "\n"
600 "#ifdef USESHADOWMAPCUBE\n"
601 "# extension GL_EXT_gpu_shader4 : enable\n"
602 "#endif\n"
603 "\n"
604 "//#ifdef USESHADOWSAMPLER\n"
605 "//# extension GL_ARB_shadow : enable\n"
606 "//#endif\n"
607 "\n"
608 "//#ifdef __GLSL_CG_DATA_TYPES\n"
609 "//# define myhalf half\n"
610 "//# define myhalf2 half2\n"
611 "//# define myhalf3 half3\n"
612 "//# define myhalf4 half4\n"
613 "//#else\n"
614 "# define myhalf float\n"
615 "# define myhalf2 vec2\n"
616 "# define myhalf3 vec3\n"
617 "# define myhalf4 vec4\n"
618 "//#endif\n"
619 "\n"
620 "#ifdef VERTEX_SHADER\n"
621 "uniform mat4 ModelViewProjectionMatrix;\n"
622 "#endif\n"
623 "\n"
624 "#ifdef MODE_DEPTH_OR_SHADOW\n"
625 "#ifdef VERTEX_SHADER\n"
626 "void main(void)\n"
627 "{\n"
628 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
629 "}\n"
630 "#endif\n"
631 "#else // !MODE_DEPTH_ORSHADOW\n"
632 "\n"
633 "\n"
634 "\n"
635 "\n"
636 "#ifdef MODE_SHOWDEPTH\n"
637 "#ifdef VERTEX_SHADER\n"
638 "void main(void)\n"
639 "{\n"
640 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
641 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
642 "}\n"
643 "#endif\n"
644 "\n"
645 "#ifdef FRAGMENT_SHADER\n"
646 "void main(void)\n"
647 "{\n"
648 "       gl_FragColor = gl_Color;\n"
649 "}\n"
650 "#endif\n"
651 "#else // !MODE_SHOWDEPTH\n"
652 "\n"
653 "\n"
654 "\n"
655 "\n"
656 "#ifdef MODE_POSTPROCESS\n"
657 "varying vec2 TexCoord1;\n"
658 "varying vec2 TexCoord2;\n"
659 "\n"
660 "#ifdef VERTEX_SHADER\n"
661 "void main(void)\n"
662 "{\n"
663 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
664 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
665 "#ifdef USEBLOOM\n"
666 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
667 "#endif\n"
668 "}\n"
669 "#endif\n"
670 "\n"
671 "#ifdef FRAGMENT_SHADER\n"
672 "uniform sampler2D Texture_First;\n"
673 "#ifdef USEBLOOM\n"
674 "uniform sampler2D Texture_Second;\n"
675 "#endif\n"
676 "#ifdef USEGAMMARAMPS\n"
677 "uniform sampler2D Texture_GammaRamps;\n"
678 "#endif\n"
679 "#ifdef USESATURATION\n"
680 "uniform float Saturation;\n"
681 "#endif\n"
682 "#ifdef USEVIEWTINT\n"
683 "uniform vec4 ViewTintColor;\n"
684 "#endif\n"
685 "//uncomment these if you want to use them:\n"
686 "uniform vec4 UserVec1;\n"
687 "uniform vec4 UserVec2;\n"
688 "// uniform vec4 UserVec3;\n"
689 "// uniform vec4 UserVec4;\n"
690 "// uniform float ClientTime;\n"
691 "uniform vec2 PixelSize;\n"
692 "void main(void)\n"
693 "{\n"
694 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
695 "#ifdef USEBLOOM\n"
696 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
697 "#endif\n"
698 "#ifdef USEVIEWTINT\n"
699 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
700 "#endif\n"
701 "\n"
702 "#ifdef USEPOSTPROCESSING\n"
703 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
704 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
705 "       float sobel = 1.0;\n"
706 "       // vec2 ts = textureSize(Texture_First, 0);\n"
707 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
708 "       vec2 px = PixelSize;\n"
709 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
710 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
711 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
712 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
713 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
714 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
715 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
716 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
717 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
718 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
719 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
720 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
721 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
722 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
723 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
724 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
725 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
726 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
727 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
728 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
729 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
730 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
731 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
732 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
733 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
734 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
735 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
736 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
737 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
738 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
739 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
740 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
741 "#endif\n"
742 "\n"
743 "#ifdef USESATURATION\n"
744 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
745 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
746 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
747 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
748 "#endif\n"
749 "\n"
750 "#ifdef USEGAMMARAMPS\n"
751 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
752 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
753 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
754 "#endif\n"
755 "}\n"
756 "#endif\n"
757 "#else // !MODE_POSTPROCESS\n"
758 "\n"
759 "\n"
760 "\n"
761 "\n"
762 "#ifdef MODE_GENERIC\n"
763 "#ifdef USEDIFFUSE\n"
764 "varying vec2 TexCoord1;\n"
765 "#endif\n"
766 "#ifdef USESPECULAR\n"
767 "varying vec2 TexCoord2;\n"
768 "#endif\n"
769 "#ifdef VERTEX_SHADER\n"
770 "void main(void)\n"
771 "{\n"
772 "       gl_FrontColor = gl_Color;\n"
773 "#ifdef USEDIFFUSE\n"
774 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
775 "#endif\n"
776 "#ifdef USESPECULAR\n"
777 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
778 "#endif\n"
779 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
780 "}\n"
781 "#endif\n"
782 "\n"
783 "#ifdef FRAGMENT_SHADER\n"
784 "#ifdef USEDIFFUSE\n"
785 "uniform sampler2D Texture_First;\n"
786 "#endif\n"
787 "#ifdef USESPECULAR\n"
788 "uniform sampler2D Texture_Second;\n"
789 "#endif\n"
790 "\n"
791 "void main(void)\n"
792 "{\n"
793 "       gl_FragColor = gl_Color;\n"
794 "#ifdef USEDIFFUSE\n"
795 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
796 "#endif\n"
797 "\n"
798 "#ifdef USESPECULAR\n"
799 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
800 "# ifdef USECOLORMAPPING\n"
801 "       gl_FragColor *= tex2;\n"
802 "# endif\n"
803 "# ifdef USEGLOW\n"
804 "       gl_FragColor += tex2;\n"
805 "# endif\n"
806 "# ifdef USEVERTEXTEXTUREBLEND\n"
807 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
808 "# endif\n"
809 "#endif\n"
810 "}\n"
811 "#endif\n"
812 "#else // !MODE_GENERIC\n"
813 "\n"
814 "\n"
815 "\n"
816 "\n"
817 "#ifdef MODE_BLOOMBLUR\n"
818 "varying TexCoord;\n"
819 "#ifdef VERTEX_SHADER\n"
820 "void main(void)\n"
821 "{\n"
822 "       gl_FrontColor = gl_Color;\n"
823 "       TexCoord = gl_MultiTexCoord0.xy;\n"
824 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
825 "}\n"
826 "#endif\n"
827 "\n"
828 "#ifdef FRAGMENT_SHADER\n"
829 "uniform sampler2D Texture_First;\n"
830 "uniform vec4 BloomBlur_Parameters;\n"
831 "\n"
832 "void main(void)\n"
833 "{\n"
834 "       int i;\n"
835 "       vec2 tc = TexCoord;\n"
836 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
837 "       tc += BloomBlur_Parameters.xy;\n"
838 "       for (i = 1;i < SAMPLES;i++)\n"
839 "       {\n"
840 "               color += texture2D(Texture_First, tc).rgb;\n"
841 "               tc += BloomBlur_Parameters.xy;\n"
842 "       }\n"
843 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
844 "}\n"
845 "#endif\n"
846 "#else // !MODE_BLOOMBLUR\n"
847 "#ifdef MODE_REFRACTION\n"
848 "varying vec2 TexCoord;\n"
849 "varying vec4 ModelViewProjectionPosition;\n"
850 "uniform mat4 TexMatrix;\n"
851 "#ifdef VERTEX_SHADER\n"
852 "\n"
853 "void main(void)\n"
854 "{\n"
855 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
856 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
857 "       ModelViewProjectionPosition = gl_Position;\n"
858 "}\n"
859 "#endif\n"
860 "\n"
861 "#ifdef FRAGMENT_SHADER\n"
862 "uniform sampler2D Texture_Normal;\n"
863 "uniform sampler2D Texture_Refraction;\n"
864 "uniform sampler2D Texture_Reflection;\n"
865 "\n"
866 "uniform vec4 DistortScaleRefractReflect;\n"
867 "uniform vec4 ScreenScaleRefractReflect;\n"
868 "uniform vec4 ScreenCenterRefractReflect;\n"
869 "uniform vec4 RefractColor;\n"
870 "uniform vec4 ReflectColor;\n"
871 "uniform float ReflectFactor;\n"
872 "uniform float ReflectOffset;\n"
873 "\n"
874 "void main(void)\n"
875 "{\n"
876 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
877 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
878 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
879 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
880 "       // FIXME temporary hack to detect the case that the reflection\n"
881 "       // gets blackened at edges due to leaving the area that contains actual\n"
882 "       // content.\n"
883 "       // Remove this 'ack once we have a better way to stop this thing from\n"
884 "       // 'appening.\n"
885 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
886 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
887 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
888 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
889 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
890 "       gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
891 "}\n"
892 "#endif\n"
893 "#else // !MODE_REFRACTION\n"
894 "\n"
895 "\n"
896 "\n"
897 "\n"
898 "#ifdef MODE_WATER\n"
899 "varying vec2 TexCoord;\n"
900 "varying vec3 EyeVector;\n"
901 "varying vec4 ModelViewProjectionPosition;\n"
902 "#ifdef VERTEX_SHADER\n"
903 "uniform vec3 EyePosition;\n"
904 "uniform mat4 TexMatrix;\n"
905 "\n"
906 "void main(void)\n"
907 "{\n"
908 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
909 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
910 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
911 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
912 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
913 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
914 "       ModelViewProjectionPosition = gl_Position;\n"
915 "}\n"
916 "#endif\n"
917 "\n"
918 "#ifdef FRAGMENT_SHADER\n"
919 "uniform sampler2D Texture_Normal;\n"
920 "uniform sampler2D Texture_Refraction;\n"
921 "uniform sampler2D Texture_Reflection;\n"
922 "\n"
923 "uniform vec4 DistortScaleRefractReflect;\n"
924 "uniform vec4 ScreenScaleRefractReflect;\n"
925 "uniform vec4 ScreenCenterRefractReflect;\n"
926 "uniform vec4 RefractColor;\n"
927 "uniform vec4 ReflectColor;\n"
928 "uniform float ReflectFactor;\n"
929 "uniform float ReflectOffset;\n"
930 "uniform float ClientTime;\n"
931 "#ifdef USENORMALMAPSCROLLBLEND\n"
932 "uniform vec2 NormalmapScrollBlend;\n"
933 "#endif\n"
934 "\n"
935 "void main(void)\n"
936 "{\n"
937 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
938 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
939 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
940 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
941 "       // slight water animation via 2 layer scrolling (todo: tweak)\n"
942 "       #ifdef USENORMALMAPSCROLLBLEND\n"
943 "               vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
944 "               normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
945 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
946 "       #else\n"
947 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
948 "       #endif\n"
949 "       // FIXME temporary hack to detect the case that the reflection\n"
950 "       // gets blackened at edges due to leaving the area that contains actual\n"
951 "       // content.\n"
952 "       // Remove this 'ack once we have a better way to stop this thing from\n"
953 "       // 'appening.\n"
954 "       float f1 = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
955 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
956 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
957 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
958 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f1);\n"
959 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
960 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
961 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
962 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
963 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
964 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
965 "       gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
966 "       gl_FragColor.a = f1 + 0.5;\n"
967 "}\n"
968 "#endif\n"
969 "#else // !MODE_WATER\n"
970 "\n"
971 "\n"
972 "\n"
973 "\n"
974 "// common definitions between vertex shader and fragment shader:\n"
975 "\n"
976 "varying vec2 TexCoord;\n"
977 "#ifdef USEVERTEXTEXTUREBLEND\n"
978 "varying vec2 TexCoord2;\n"
979 "#endif\n"
980 "#ifdef USELIGHTMAP\n"
981 "varying vec2 TexCoordLightmap;\n"
982 "#endif\n"
983 "\n"
984 "#ifdef MODE_LIGHTSOURCE\n"
985 "varying vec3 CubeVector;\n"
986 "#endif\n"
987 "\n"
988 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
989 "varying vec3 LightVector;\n"
990 "#endif\n"
991 "\n"
992 "#ifdef USEEYEVECTOR\n"
993 "varying vec3 EyeVector;\n"
994 "#endif\n"
995 "#ifdef USEFOG\n"
996 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
997 "#endif\n"
998 "\n"
999 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1000 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1001 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1002 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
1003 "#endif\n"
1004 "\n"
1005 "#ifdef USEREFLECTION\n"
1006 "varying vec4 ModelViewProjectionPosition;\n"
1007 "#endif\n"
1008 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1009 "uniform vec3 LightPosition;\n"
1010 "varying vec4 ModelViewPosition;\n"
1011 "#endif\n"
1012 "\n"
1013 "#ifdef MODE_LIGHTSOURCE\n"
1014 "uniform vec3 LightPosition;\n"
1015 "#endif\n"
1016 "uniform vec3 EyePosition;\n"
1017 "#ifdef MODE_LIGHTDIRECTION\n"
1018 "uniform vec3 LightDir;\n"
1019 "#endif\n"
1020 "uniform vec4 FogPlane;\n"
1021 "\n"
1022 "#ifdef USESHADOWMAPORTHO\n"
1023 "varying vec3 ShadowMapTC;\n"
1024 "#endif\n"
1025 "\n"
1026 "\n"
1027 "\n"
1028 "\n"
1029 "\n"
1030 "// 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"
1031 "\n"
1032 "// fragment shader specific:\n"
1033 "#ifdef FRAGMENT_SHADER\n"
1034 "\n"
1035 "uniform sampler2D Texture_Normal;\n"
1036 "uniform sampler2D Texture_Color;\n"
1037 "uniform sampler2D Texture_Gloss;\n"
1038 "#ifdef USEGLOW\n"
1039 "uniform sampler2D Texture_Glow;\n"
1040 "#endif\n"
1041 "#ifdef USEVERTEXTEXTUREBLEND\n"
1042 "uniform sampler2D Texture_SecondaryNormal;\n"
1043 "uniform sampler2D Texture_SecondaryColor;\n"
1044 "uniform sampler2D Texture_SecondaryGloss;\n"
1045 "#ifdef USEGLOW\n"
1046 "uniform sampler2D Texture_SecondaryGlow;\n"
1047 "#endif\n"
1048 "#endif\n"
1049 "#ifdef USECOLORMAPPING\n"
1050 "uniform sampler2D Texture_Pants;\n"
1051 "uniform sampler2D Texture_Shirt;\n"
1052 "#endif\n"
1053 "#ifdef USEFOG\n"
1054 "#ifdef USEFOGHEIGHTTEXTURE\n"
1055 "uniform sampler2D Texture_FogHeightTexture;\n"
1056 "#endif\n"
1057 "uniform sampler2D Texture_FogMask;\n"
1058 "#endif\n"
1059 "#ifdef USELIGHTMAP\n"
1060 "uniform sampler2D Texture_Lightmap;\n"
1061 "#endif\n"
1062 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1063 "uniform sampler2D Texture_Deluxemap;\n"
1064 "#endif\n"
1065 "#ifdef USEREFLECTION\n"
1066 "uniform sampler2D Texture_Reflection;\n"
1067 "#endif\n"
1068 "\n"
1069 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1070 "uniform sampler2D Texture_ScreenDepth;\n"
1071 "uniform sampler2D Texture_ScreenNormalMap;\n"
1072 "#endif\n"
1073 "#ifdef USEDEFERREDLIGHTMAP\n"
1074 "uniform sampler2D Texture_ScreenDiffuse;\n"
1075 "uniform sampler2D Texture_ScreenSpecular;\n"
1076 "#endif\n"
1077 "\n"
1078 "uniform myhalf3 Color_Pants;\n"
1079 "uniform myhalf3 Color_Shirt;\n"
1080 "uniform myhalf3 FogColor;\n"
1081 "\n"
1082 "#ifdef USEFOG\n"
1083 "uniform float FogRangeRecip;\n"
1084 "uniform float FogPlaneViewDist;\n"
1085 "uniform float FogHeightFade;\n"
1086 "vec3 FogVertex(vec3 surfacecolor)\n"
1087 "{\n"
1088 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1089 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1090 "       float fogfrac;\n"
1091 "#ifdef USEFOGHEIGHTTEXTURE\n"
1092 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1093 "       fogfrac = fogheightpixel.a;\n"
1094 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1095 "#else\n"
1096 "# ifdef USEFOGOUTSIDE\n"
1097 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1098 "# else\n"
1099 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1100 "# endif\n"
1101 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1102 "#endif\n"
1103 "}\n"
1104 "#endif\n"
1105 "\n"
1106 "#ifdef USEOFFSETMAPPING\n"
1107 "uniform float OffsetMapping_Scale;\n"
1108 "vec2 OffsetMapping(vec2 TexCoord)\n"
1109 "{\n"
1110 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1111 "       // 14 sample relief mapping: linear search and then binary search\n"
1112 "       // this basically steps forward a small amount repeatedly until it finds\n"
1113 "       // itself inside solid, then jitters forward and back using decreasing\n"
1114 "       // amounts to find the impact\n"
1115 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1116 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1117 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1118 "       vec3 RT = vec3(TexCoord, 1);\n"
1119 "       OffsetVector *= 0.1;\n"
1120 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1121 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1122 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1123 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1124 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1125 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1126 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1127 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1128 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1129 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1130 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1131 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1132 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1133 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1134 "       return RT.xy;\n"
1135 "#else\n"
1136 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1137 "       // this basically moves forward the full distance, and then backs up based\n"
1138 "       // on height of samples\n"
1139 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1140 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1141 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1142 "       TexCoord += OffsetVector;\n"
1143 "       OffsetVector *= 0.333;\n"
1144 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1145 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1146 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1147 "       return TexCoord;\n"
1148 "#endif\n"
1149 "}\n"
1150 "#endif // USEOFFSETMAPPING\n"
1151 "\n"
1152 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1153 "uniform sampler2D Texture_Attenuation;\n"
1154 "uniform samplerCube Texture_Cube;\n"
1155 "#endif\n"
1156 "\n"
1157 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1158 "\n"
1159 "#ifdef USESHADOWMAPRECT\n"
1160 "# ifdef USESHADOWSAMPLER\n"
1161 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1162 "# else\n"
1163 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1164 "# endif\n"
1165 "#endif\n"
1166 "\n"
1167 "#ifdef USESHADOWMAP2D\n"
1168 "# ifdef USESHADOWSAMPLER\n"
1169 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1170 "# else\n"
1171 "uniform sampler2D Texture_ShadowMap2D;\n"
1172 "# endif\n"
1173 "#endif\n"
1174 "\n"
1175 "#ifdef USESHADOWMAPVSDCT\n"
1176 "uniform samplerCube Texture_CubeProjection;\n"
1177 "#endif\n"
1178 "\n"
1179 "#ifdef USESHADOWMAPCUBE\n"
1180 "# ifdef USESHADOWSAMPLER\n"
1181 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1182 "# else\n"
1183 "uniform samplerCube Texture_ShadowMapCube;\n"
1184 "# endif\n"
1185 "#endif\n"
1186 "\n"
1187 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1188 "uniform vec2 ShadowMap_TextureScale;\n"
1189 "uniform vec4 ShadowMap_Parameters;\n"
1190 "#endif\n"
1191 "\n"
1192 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1193 "# ifdef USESHADOWMAPORTHO\n"
1194 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1195 "# else\n"
1196 "#  ifdef USESHADOWMAPVSDCT\n"
1197 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1198 "{\n"
1199 "       vec3 adir = abs(dir);\n"
1200 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1201 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1202 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1203 "}\n"
1204 "#  else\n"
1205 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1206 "{\n"
1207 "       vec3 adir = abs(dir);\n"
1208 "       float ma = adir.z;\n"
1209 "       vec4 proj = vec4(dir, 2.5);\n"
1210 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1211 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1212 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1213 "       return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1214 "}\n"
1215 "#  endif\n"
1216 "# endif\n"
1217 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1218 "\n"
1219 "#ifdef USESHADOWMAPCUBE\n"
1220 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1221 "{\n"
1222 "       vec3 adir = abs(dir);\n"
1223 "       return vec4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
1224 "}\n"
1225 "#endif\n"
1226 "\n"
1227 "# ifdef USESHADOWMAPRECT\n"
1228 "float ShadowMapCompare(vec3 dir)\n"
1229 "{\n"
1230 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1231 "       float f;\n"
1232 "#  ifdef USESHADOWSAMPLER\n"
1233 "\n"
1234 "#    ifdef USESHADOWMAPPCF\n"
1235 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1236 "       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"
1237 "#    else\n"
1238 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1239 "#    endif\n"
1240 "\n"
1241 "#  else\n"
1242 "\n"
1243 "#    ifdef USESHADOWMAPPCF\n"
1244 "#      if USESHADOWMAPPCF > 1\n"
1245 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1246 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1247 "       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"
1248 "       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"
1249 "       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"
1250 "       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"
1251 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1252 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1253 "#      else\n"
1254 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1255 "       vec2 offset = fract(shadowmaptc.xy);\n"
1256 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1257 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1258 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1259 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1260 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1261 "#      endif\n"
1262 "#    else\n"
1263 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1264 "#    endif\n"
1265 "\n"
1266 "#  endif\n"
1267 "#  ifdef USESHADOWMAPORTHO\n"
1268 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1269 "#  else\n"
1270 "       return f;\n"
1271 "#  endif\n"
1272 "}\n"
1273 "# endif\n"
1274 "\n"
1275 "# ifdef USESHADOWMAP2D\n"
1276 "float ShadowMapCompare(vec3 dir)\n"
1277 "{\n"
1278 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1279 "       float f;\n"
1280 "\n"
1281 "#  ifdef USESHADOWSAMPLER\n"
1282 "#    ifdef USESHADOWMAPPCF\n"
1283 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1284 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1285 "       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"
1286 "#    else\n"
1287 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1288 "#    endif\n"
1289 "#  else\n"
1290 "#    ifdef USESHADOWMAPPCF\n"
1291 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1292 "#      ifdef GL_ARB_texture_gather\n"
1293 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1294 "#      else\n"
1295 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1296 "#      endif\n"
1297 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1298 "#      if USESHADOWMAPPCF > 1\n"
1299 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1300 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1301 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1302 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1303 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1304 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1305 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1306 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1307 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1308 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1309 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1310 "       locols.yz += group2.ab;\n"
1311 "       hicols.yz += group8.rg;\n"
1312 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1313 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1314 "                               mix(locols, hicols, offset.y);\n"
1315 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1316 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1317 "       f = dot(cols, vec4(1.0/25.0));\n"
1318 "#      else\n"
1319 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1320 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1321 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1322 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1323 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1324 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1325 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1326 "#      endif\n"
1327 "#     else\n"
1328 "#      ifdef GL_EXT_gpu_shader4\n"
1329 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1330 "#      else\n"
1331 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1332 "#      endif\n"
1333 "#      if USESHADOWMAPPCF > 1\n"
1334 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1335 "       center *= ShadowMap_TextureScale;\n"
1336 "       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"
1337 "       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"
1338 "       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"
1339 "       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"
1340 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1341 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1342 "#      else\n"
1343 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1344 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1345 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1346 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1347 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1348 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1349 "#      endif\n"
1350 "#     endif\n"
1351 "#    else\n"
1352 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1353 "#    endif\n"
1354 "#  endif\n"
1355 "#  ifdef USESHADOWMAPORTHO\n"
1356 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1357 "#  else\n"
1358 "       return f;\n"
1359 "#  endif\n"
1360 "}\n"
1361 "# endif\n"
1362 "\n"
1363 "# ifdef USESHADOWMAPCUBE\n"
1364 "float ShadowMapCompare(vec3 dir)\n"
1365 "{\n"
1366 "       // apply depth texture cubemap as light filter\n"
1367 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1368 "       float f;\n"
1369 "#  ifdef USESHADOWSAMPLER\n"
1370 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1371 "#  else\n"
1372 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1373 "#  endif\n"
1374 "       return f;\n"
1375 "}\n"
1376 "# endif\n"
1377 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1378 "#endif // FRAGMENT_SHADER\n"
1379 "\n"
1380 "\n"
1381 "\n"
1382 "\n"
1383 "#ifdef MODE_DEFERREDGEOMETRY\n"
1384 "#ifdef VERTEX_SHADER\n"
1385 "uniform mat4 TexMatrix;\n"
1386 "#ifdef USEVERTEXTEXTUREBLEND\n"
1387 "uniform mat4 BackgroundTexMatrix;\n"
1388 "#endif\n"
1389 "uniform mat4 ModelViewMatrix;\n"
1390 "void main(void)\n"
1391 "{\n"
1392 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1393 "#ifdef USEVERTEXTEXTUREBLEND\n"
1394 "       gl_FrontColor = gl_Color;\n"
1395 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1396 "#endif\n"
1397 "\n"
1398 "       // transform unnormalized eye direction into tangent space\n"
1399 "#ifdef USEOFFSETMAPPING\n"
1400 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1401 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1402 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1403 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1404 "#endif\n"
1405 "\n"
1406 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1407 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1408 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1409 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1410 "}\n"
1411 "#endif // VERTEX_SHADER\n"
1412 "\n"
1413 "#ifdef FRAGMENT_SHADER\n"
1414 "void main(void)\n"
1415 "{\n"
1416 "#ifdef USEOFFSETMAPPING\n"
1417 "       // apply offsetmapping\n"
1418 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1419 "#define TexCoord TexCoordOffset\n"
1420 "#endif\n"
1421 "\n"
1422 "#ifdef USEALPHAKILL\n"
1423 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1424 "               discard;\n"
1425 "#endif\n"
1426 "\n"
1427 "#ifdef USEVERTEXTEXTUREBLEND\n"
1428 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1429 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1430 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1431 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1432 "#endif\n"
1433 "\n"
1434 "#ifdef USEVERTEXTEXTUREBLEND\n"
1435 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1436 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1437 "#else\n"
1438 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1439 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1440 "#endif\n"
1441 "\n"
1442 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1443 "}\n"
1444 "#endif // FRAGMENT_SHADER\n"
1445 "#else // !MODE_DEFERREDGEOMETRY\n"
1446 "\n"
1447 "\n"
1448 "\n"
1449 "\n"
1450 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1451 "#ifdef VERTEX_SHADER\n"
1452 "uniform mat4 ModelViewMatrix;\n"
1453 "void main(void)\n"
1454 "{\n"
1455 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1456 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1457 "}\n"
1458 "#endif // VERTEX_SHADER\n"
1459 "\n"
1460 "#ifdef FRAGMENT_SHADER\n"
1461 "uniform mat4 ViewToLight;\n"
1462 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1463 "uniform vec2 ScreenToDepth;\n"
1464 "uniform myhalf3 DeferredColor_Ambient;\n"
1465 "uniform myhalf3 DeferredColor_Diffuse;\n"
1466 "#ifdef USESPECULAR\n"
1467 "uniform myhalf3 DeferredColor_Specular;\n"
1468 "uniform myhalf SpecularPower;\n"
1469 "#endif\n"
1470 "uniform myhalf2 PixelToScreenTexCoord;\n"
1471 "void main(void)\n"
1472 "{\n"
1473 "       // calculate viewspace pixel position\n"
1474 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1475 "       vec3 position;\n"
1476 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1477 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1478 "       // decode viewspace pixel normal\n"
1479 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1480 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1481 "       // surfacenormal = pixel normal in viewspace\n"
1482 "       // LightVector = pixel to light in viewspace\n"
1483 "       // CubeVector = position in lightspace\n"
1484 "       // eyevector = pixel to view in viewspace\n"
1485 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1486 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1487 "#ifdef USEDIFFUSE\n"
1488 "       // calculate diffuse shading\n"
1489 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1490 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1491 "#endif\n"
1492 "#ifdef USESPECULAR\n"
1493 "       // calculate directional shading\n"
1494 "       vec3 eyevector = position * -1.0;\n"
1495 "#  ifdef USEEXACTSPECULARMATH\n"
1496 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1497 "#  else\n"
1498 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1499 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1500 "#  endif\n"
1501 "#endif\n"
1502 "\n"
1503 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1504 "       fade *= ShadowMapCompare(CubeVector);\n"
1505 "#endif\n"
1506 "\n"
1507 "#ifdef USEDIFFUSE\n"
1508 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1509 "#else\n"
1510 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1511 "#endif\n"
1512 "#ifdef USESPECULAR\n"
1513 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1514 "#else\n"
1515 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1516 "#endif\n"
1517 "\n"
1518 "# ifdef USECUBEFILTER\n"
1519 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1520 "       gl_FragData[0].rgb *= cubecolor;\n"
1521 "       gl_FragData[1].rgb *= cubecolor;\n"
1522 "# endif\n"
1523 "}\n"
1524 "#endif // FRAGMENT_SHADER\n"
1525 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1526 "\n"
1527 "\n"
1528 "\n"
1529 "\n"
1530 "#ifdef VERTEX_SHADER\n"
1531 "uniform mat4 TexMatrix;\n"
1532 "#ifdef USEVERTEXTEXTUREBLEND\n"
1533 "uniform mat4 BackgroundTexMatrix;\n"
1534 "#endif\n"
1535 "#ifdef MODE_LIGHTSOURCE\n"
1536 "uniform mat4 ModelToLight;\n"
1537 "#endif\n"
1538 "#ifdef USESHADOWMAPORTHO\n"
1539 "uniform mat4 ShadowMapMatrix;\n"
1540 "#endif\n"
1541 "void main(void)\n"
1542 "{\n"
1543 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1544 "       gl_FrontColor = gl_Color;\n"
1545 "#endif\n"
1546 "       // copy the surface texcoord\n"
1547 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1548 "#ifdef USEVERTEXTEXTUREBLEND\n"
1549 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1550 "#endif\n"
1551 "#ifdef USELIGHTMAP\n"
1552 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1553 "#endif\n"
1554 "\n"
1555 "#ifdef MODE_LIGHTSOURCE\n"
1556 "       // transform vertex position into light attenuation/cubemap space\n"
1557 "       // (-1 to +1 across the light box)\n"
1558 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1559 "\n"
1560 "# ifdef USEDIFFUSE\n"
1561 "       // transform unnormalized light direction into tangent space\n"
1562 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1563 "       //  normalize it per pixel)\n"
1564 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1565 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1566 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1567 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1568 "# endif\n"
1569 "#endif\n"
1570 "\n"
1571 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1572 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1573 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1574 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1575 "#endif\n"
1576 "\n"
1577 "       // transform unnormalized eye direction into tangent space\n"
1578 "#ifdef USEEYEVECTOR\n"
1579 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1580 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1581 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1582 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1583 "#endif\n"
1584 "\n"
1585 "#ifdef USEFOG\n"
1586 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1587 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1588 "#endif\n"
1589 "\n"
1590 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1591 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1592 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1593 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1594 "#endif\n"
1595 "\n"
1596 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1597 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1598 "\n"
1599 "#ifdef USESHADOWMAPORTHO\n"
1600 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1601 "#endif\n"
1602 "\n"
1603 "#ifdef USEREFLECTION\n"
1604 "       ModelViewProjectionPosition = gl_Position;\n"
1605 "#endif\n"
1606 "}\n"
1607 "#endif // VERTEX_SHADER\n"
1608 "\n"
1609 "\n"
1610 "\n"
1611 "\n"
1612 "#ifdef FRAGMENT_SHADER\n"
1613 "#ifdef USEDEFERREDLIGHTMAP\n"
1614 "uniform myhalf2 PixelToScreenTexCoord;\n"
1615 "uniform myhalf3 DeferredMod_Diffuse;\n"
1616 "uniform myhalf3 DeferredMod_Specular;\n"
1617 "#endif\n"
1618 "uniform myhalf3 Color_Ambient;\n"
1619 "uniform myhalf3 Color_Diffuse;\n"
1620 "uniform myhalf3 Color_Specular;\n"
1621 "uniform myhalf SpecularPower;\n"
1622 "#ifdef USEGLOW\n"
1623 "uniform myhalf3 Color_Glow;\n"
1624 "#endif\n"
1625 "uniform myhalf Alpha;\n"
1626 "#ifdef USEREFLECTION\n"
1627 "uniform vec4 DistortScaleRefractReflect;\n"
1628 "uniform vec4 ScreenScaleRefractReflect;\n"
1629 "uniform vec4 ScreenCenterRefractReflect;\n"
1630 "uniform myhalf4 ReflectColor;\n"
1631 "#endif\n"
1632 "#ifdef USEREFLECTCUBE\n"
1633 "uniform mat4 ModelToReflectCube;\n"
1634 "uniform sampler2D Texture_ReflectMask;\n"
1635 "uniform samplerCube Texture_ReflectCube;\n"
1636 "#endif\n"
1637 "#ifdef MODE_LIGHTDIRECTION\n"
1638 "uniform myhalf3 LightColor;\n"
1639 "#endif\n"
1640 "#ifdef MODE_LIGHTSOURCE\n"
1641 "uniform myhalf3 LightColor;\n"
1642 "#endif\n"
1643 "void main(void)\n"
1644 "{\n"
1645 "#ifdef USEOFFSETMAPPING\n"
1646 "       // apply offsetmapping\n"
1647 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1648 "#define TexCoord TexCoordOffset\n"
1649 "#endif\n"
1650 "\n"
1651 "       // combine the diffuse textures (base, pants, shirt)\n"
1652 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1653 "#ifdef USEALPHAKILL\n"
1654 "       if (color.a < 0.5)\n"
1655 "               discard;\n"
1656 "#endif\n"
1657 "       color.a *= Alpha;\n"
1658 "#ifdef USECOLORMAPPING\n"
1659 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1660 "#endif\n"
1661 "#ifdef USEVERTEXTEXTUREBLEND\n"
1662 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1663 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1664 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1665 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1666 "       color.a = 1.0;\n"
1667 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1668 "#endif\n"
1669 "\n"
1670 "       // get the surface normal\n"
1671 "#ifdef USEVERTEXTEXTUREBLEND\n"
1672 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1673 "#else\n"
1674 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1675 "#endif\n"
1676 "\n"
1677 "       // get the material colors\n"
1678 "       myhalf3 diffusetex = color.rgb;\n"
1679 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1680 "# ifdef USEVERTEXTEXTUREBLEND\n"
1681 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1682 "# else\n"
1683 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1684 "# endif\n"
1685 "#endif\n"
1686 "\n"
1687 "#ifdef USEREFLECTCUBE\n"
1688 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1689 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1690 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1691 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1692 "#endif\n"
1693 "\n"
1694 "\n"
1695 "\n"
1696 "\n"
1697 "#ifdef MODE_LIGHTSOURCE\n"
1698 "       // light source\n"
1699 "#ifdef USEDIFFUSE\n"
1700 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1701 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1702 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1703 "#ifdef USESPECULAR\n"
1704 "#ifdef USEEXACTSPECULARMATH\n"
1705 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1706 "#else\n"
1707 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1708 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1709 "#endif\n"
1710 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1711 "#endif\n"
1712 "#else\n"
1713 "       color.rgb = diffusetex * Color_Ambient;\n"
1714 "#endif\n"
1715 "       color.rgb *= LightColor;\n"
1716 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1717 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1718 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1719 "#endif\n"
1720 "# ifdef USECUBEFILTER\n"
1721 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1722 "# endif\n"
1723 "#endif // MODE_LIGHTSOURCE\n"
1724 "\n"
1725 "\n"
1726 "\n"
1727 "\n"
1728 "#ifdef MODE_LIGHTDIRECTION\n"
1729 "#define SHADING\n"
1730 "#ifdef USEDIFFUSE\n"
1731 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1732 "#endif\n"
1733 "#define lightcolor LightColor\n"
1734 "#endif // MODE_LIGHTDIRECTION\n"
1735 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1736 "#define SHADING\n"
1737 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1738 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1739 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1740 "       // convert modelspace light vector to tangentspace\n"
1741 "       myhalf3 lightnormal;\n"
1742 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1743 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1744 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1745 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1746 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1747 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1748 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1749 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1750 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1751 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1752 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1753 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1754 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1755 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1756 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1757 "#define SHADING\n"
1758 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1759 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1760 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1761 "#endif\n"
1762 "\n"
1763 "\n"
1764 "\n"
1765 "\n"
1766 "#ifdef MODE_FAKELIGHT\n"
1767 "#define SHADING\n"
1768 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1769 "myhalf3 lightcolor = myhalf3(1.0);\n"
1770 "#endif // MODE_FAKELIGHT\n"
1771 "\n"
1772 "\n"
1773 "\n"
1774 "\n"
1775 "#ifdef MODE_LIGHTMAP\n"
1776 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1777 "#endif // MODE_LIGHTMAP\n"
1778 "#ifdef MODE_VERTEXCOLOR\n"
1779 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1780 "#endif // MODE_VERTEXCOLOR\n"
1781 "#ifdef MODE_FLATCOLOR\n"
1782 "       color.rgb = diffusetex * Color_Ambient;\n"
1783 "#endif // MODE_FLATCOLOR\n"
1784 "\n"
1785 "\n"
1786 "\n"
1787 "\n"
1788 "#ifdef SHADING\n"
1789 "# ifdef USEDIFFUSE\n"
1790 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1791 "#  ifdef USESPECULAR\n"
1792 "#   ifdef USEEXACTSPECULARMATH\n"
1793 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1794 "#   else\n"
1795 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1796 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1797 "#   endif\n"
1798 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1799 "#  else\n"
1800 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1801 "#  endif\n"
1802 "# else\n"
1803 "       color.rgb = diffusetex * Color_Ambient;\n"
1804 "# endif\n"
1805 "#endif\n"
1806 "\n"
1807 "#ifdef USESHADOWMAPORTHO\n"
1808 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1809 "#endif\n"
1810 "\n"
1811 "#ifdef USEDEFERREDLIGHTMAP\n"
1812 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1813 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1814 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1815 "#endif\n"
1816 "\n"
1817 "#ifdef USEGLOW\n"
1818 "#ifdef USEVERTEXTEXTUREBLEND\n"
1819 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1820 "#else\n"
1821 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1822 "#endif\n"
1823 "#endif\n"
1824 "\n"
1825 "#ifdef USEFOG\n"
1826 "       color.rgb = FogVertex(color.rgb);\n"
1827 "#endif\n"
1828 "\n"
1829 "       // 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"
1830 "#ifdef USEREFLECTION\n"
1831 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1832 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1833 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1834 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1835 "       // FIXME temporary hack to detect the case that the reflection\n"
1836 "       // gets blackened at edges due to leaving the area that contains actual\n"
1837 "       // content.\n"
1838 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1839 "       // 'appening.\n"
1840 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1841 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1842 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1843 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1844 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1845 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1846 "#endif\n"
1847 "\n"
1848 "       gl_FragColor = vec4(color);\n"
1849 "}\n"
1850 "#endif // FRAGMENT_SHADER\n"
1851 "\n"
1852 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1853 "#endif // !MODE_DEFERREDGEOMETRY\n"
1854 "#endif // !MODE_WATER\n"
1855 "#endif // !MODE_REFRACTION\n"
1856 "#endif // !MODE_BLOOMBLUR\n"
1857 "#endif // !MODE_GENERIC\n"
1858 "#endif // !MODE_POSTPROCESS\n"
1859 "#endif // !MODE_SHOWDEPTH\n"
1860 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1861 ;
1862
1863 /*
1864 =========================================================================================================================================================
1865
1866
1867
1868 =========================================================================================================================================================
1869
1870
1871
1872 =========================================================================================================================================================
1873
1874
1875
1876 =========================================================================================================================================================
1877
1878
1879
1880 =========================================================================================================================================================
1881
1882
1883
1884 =========================================================================================================================================================
1885
1886
1887
1888 =========================================================================================================================================================
1889 */
1890
1891 const char *builtincgshaderstring =
1892 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1893 "// written by Forest 'LordHavoc' Hale\n"
1894 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1895 "\n"
1896 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1897 "#if defined(USEREFLECTION)\n"
1898 "#undef USESHADOWMAPORTHO\n"
1899 "#endif\n"
1900 "\n"
1901 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1902 "# define USEFOG\n"
1903 "#endif\n"
1904 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1905 "#define USELIGHTMAP\n"
1906 "#endif\n"
1907 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1908 "#define USEEYEVECTOR\n"
1909 "#endif\n"
1910 "\n"
1911 "#ifdef FRAGMENT_SHADER\n"
1912 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1913 "#endif\n"
1914 "\n"
1915 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1916 "#ifdef VERTEX_SHADER\n"
1917 "void main\n"
1918 "(\n"
1919 "float4 gl_Vertex : POSITION,\n"
1920 "uniform float4x4 ModelViewProjectionMatrix,\n"
1921 "out float4 gl_Position : POSITION\n"
1922 ")\n"
1923 "{\n"
1924 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1925 "}\n"
1926 "#endif\n"
1927 "#else // !MODE_DEPTH_ORSHADOW\n"
1928 "\n"
1929 "\n"
1930 "\n"
1931 "\n"
1932 "#ifdef MODE_SHOWDEPTH\n"
1933 "#ifdef VERTEX_SHADER\n"
1934 "void main\n"
1935 "(\n"
1936 "float4 gl_Vertex : POSITION,\n"
1937 "uniform float4x4 ModelViewProjectionMatrix,\n"
1938 "out float4 gl_Position : POSITION,\n"
1939 "out float4 gl_FrontColor : COLOR0\n"
1940 ")\n"
1941 "{\n"
1942 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1943 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1944 "}\n"
1945 "#endif\n"
1946 "\n"
1947 "#ifdef FRAGMENT_SHADER\n"
1948 "void main\n"
1949 "(\n"
1950 "float4 gl_FrontColor : COLOR0,\n"
1951 "out float4 gl_FragColor : COLOR\n"
1952 ")\n"
1953 "{\n"
1954 "       gl_FragColor = gl_FrontColor;\n"
1955 "}\n"
1956 "#endif\n"
1957 "#else // !MODE_SHOWDEPTH\n"
1958 "\n"
1959 "\n"
1960 "\n"
1961 "\n"
1962 "#ifdef MODE_POSTPROCESS\n"
1963 "\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 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1971 "out float4 gl_Position : POSITION,\n"
1972 "out float2 TexCoord1 : TEXCOORD0,\n"
1973 "out float2 TexCoord2 : TEXCOORD1\n"
1974 ")\n"
1975 "{\n"
1976 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1977 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1978 "#ifdef USEBLOOM\n"
1979 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1980 "#endif\n"
1981 "}\n"
1982 "#endif\n"
1983 "\n"
1984 "#ifdef FRAGMENT_SHADER\n"
1985 "void main\n"
1986 "(\n"
1987 "float2 TexCoord1 : TEXCOORD0,\n"
1988 "float2 TexCoord2 : TEXCOORD1,\n"
1989 "uniform sampler2D Texture_First,\n"
1990 "#ifdef USEBLOOM\n"
1991 "uniform sampler2D Texture_Second,\n"
1992 "#endif\n"
1993 "#ifdef USEGAMMARAMPS\n"
1994 "uniform sampler2D Texture_GammaRamps,\n"
1995 "#endif\n"
1996 "#ifdef USESATURATION\n"
1997 "uniform float Saturation,\n"
1998 "#endif\n"
1999 "#ifdef USEVIEWTINT\n"
2000 "uniform float4 ViewTintColor,\n"
2001 "#endif\n"
2002 "uniform float4 UserVec1,\n"
2003 "uniform float4 UserVec2,\n"
2004 "uniform float4 UserVec3,\n"
2005 "uniform float4 UserVec4,\n"
2006 "uniform float ClientTime,\n"
2007 "uniform float2 PixelSize,\n"
2008 "out float4 gl_FragColor : COLOR\n"
2009 ")\n"
2010 "{\n"
2011 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
2012 "#ifdef USEBLOOM\n"
2013 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
2014 "#endif\n"
2015 "#ifdef USEVIEWTINT\n"
2016 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
2017 "#endif\n"
2018 "\n"
2019 "#ifdef USEPOSTPROCESSING\n"
2020 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
2021 "// 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"
2022 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2023 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2024 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2025 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2026 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2027 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
2028 "#endif\n"
2029 "\n"
2030 "#ifdef USESATURATION\n"
2031 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2032 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2033 "       //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2034 "       gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2035 "#endif\n"
2036 "\n"
2037 "#ifdef USEGAMMARAMPS\n"
2038 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2039 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2040 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2041 "#endif\n"
2042 "}\n"
2043 "#endif\n"
2044 "#else // !MODE_POSTPROCESS\n"
2045 "\n"
2046 "\n"
2047 "\n"
2048 "\n"
2049 "#ifdef MODE_GENERIC\n"
2050 "#ifdef VERTEX_SHADER\n"
2051 "void main\n"
2052 "(\n"
2053 "float4 gl_Vertex : POSITION,\n"
2054 "uniform float4x4 ModelViewProjectionMatrix,\n"
2055 "float4 gl_Color : COLOR0,\n"
2056 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2057 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2058 "out float4 gl_Position : POSITION,\n"
2059 "out float4 gl_FrontColor : COLOR,\n"
2060 "out float2 TexCoord1 : TEXCOORD0,\n"
2061 "out float2 TexCoord2 : TEXCOORD1\n"
2062 ")\n"
2063 "{\n"
2064 "       gl_FrontColor = gl_Color;\n"
2065 "#ifdef USEDIFFUSE\n"
2066 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2067 "#endif\n"
2068 "#ifdef USESPECULAR\n"
2069 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2070 "#endif\n"
2071 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2072 "}\n"
2073 "#endif\n"
2074 "\n"
2075 "#ifdef FRAGMENT_SHADER\n"
2076 "\n"
2077 "void main\n"
2078 "(\n"
2079 "float4 gl_FrontColor : COLOR,\n"
2080 "float2 TexCoord1 : TEXCOORD0,\n"
2081 "float2 TexCoord2 : TEXCOORD1,\n"
2082 "#ifdef USEDIFFUSE\n"
2083 "uniform sampler2D Texture_First,\n"
2084 "#endif\n"
2085 "#ifdef USESPECULAR\n"
2086 "uniform sampler2D Texture_Second,\n"
2087 "#endif\n"
2088 "out float4 gl_FragColor : COLOR\n"
2089 ")\n"
2090 "{\n"
2091 "       gl_FragColor = gl_FrontColor;\n"
2092 "#ifdef USEDIFFUSE\n"
2093 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2094 "#endif\n"
2095 "\n"
2096 "#ifdef USESPECULAR\n"
2097 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2098 "# ifdef USECOLORMAPPING\n"
2099 "       gl_FragColor *= tex2;\n"
2100 "# endif\n"
2101 "# ifdef USEGLOW\n"
2102 "       gl_FragColor += tex2;\n"
2103 "# endif\n"
2104 "# ifdef USEVERTEXTEXTUREBLEND\n"
2105 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2106 "# endif\n"
2107 "#endif\n"
2108 "}\n"
2109 "#endif\n"
2110 "#else // !MODE_GENERIC\n"
2111 "\n"
2112 "\n"
2113 "\n"
2114 "\n"
2115 "#ifdef MODE_BLOOMBLUR\n"
2116 "#ifdef VERTEX_SHADER\n"
2117 "void main\n"
2118 "(\n"
2119 "float4 gl_Vertex : POSITION,\n"
2120 "uniform float4x4 ModelViewProjectionMatrix,\n"
2121 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2122 "out float4 gl_Position : POSITION,\n"
2123 "out float2 TexCoord : TEXCOORD0\n"
2124 ")\n"
2125 "{\n"
2126 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2127 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2128 "}\n"
2129 "#endif\n"
2130 "\n"
2131 "#ifdef FRAGMENT_SHADER\n"
2132 "\n"
2133 "void main\n"
2134 "(\n"
2135 "float2 TexCoord : TEXCOORD0,\n"
2136 "uniform sampler2D Texture_First,\n"
2137 "uniform float4 BloomBlur_Parameters,\n"
2138 "out float4 gl_FragColor : COLOR\n"
2139 ")\n"
2140 "{\n"
2141 "       int i;\n"
2142 "       float2 tc = TexCoord;\n"
2143 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2144 "       tc += BloomBlur_Parameters.xy;\n"
2145 "       for (i = 1;i < SAMPLES;i++)\n"
2146 "       {\n"
2147 "               color += tex2D(Texture_First, tc).rgb;\n"
2148 "               tc += BloomBlur_Parameters.xy;\n"
2149 "       }\n"
2150 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2151 "}\n"
2152 "#endif\n"
2153 "#else // !MODE_BLOOMBLUR\n"
2154 "#ifdef MODE_REFRACTION\n"
2155 "#ifdef VERTEX_SHADER\n"
2156 "void main\n"
2157 "(\n"
2158 "float4 gl_Vertex : POSITION,\n"
2159 "uniform float4x4 ModelViewProjectionMatrix,\n"
2160 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2161 "uniform float4x4 TexMatrix,\n"
2162 "uniform float3 EyePosition,\n"
2163 "out float4 gl_Position : POSITION,\n"
2164 "out float2 TexCoord : TEXCOORD0,\n"
2165 "out float3 EyeVector : TEXCOORD1,\n"
2166 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2167 ")\n"
2168 "{\n"
2169 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2170 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2171 "       ModelViewProjectionPosition = gl_Position;\n"
2172 "}\n"
2173 "#endif\n"
2174 "\n"
2175 "#ifdef FRAGMENT_SHADER\n"
2176 "void main\n"
2177 "(\n"
2178 "float2 TexCoord : TEXCOORD0,\n"
2179 "float3 EyeVector : TEXCOORD1,\n"
2180 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2181 "uniform sampler2D Texture_Normal,\n"
2182 "uniform sampler2D Texture_Refraction,\n"
2183 "uniform sampler2D Texture_Reflection,\n"
2184 "uniform float4 DistortScaleRefractReflect,\n"
2185 "uniform float4 ScreenScaleRefractReflect,\n"
2186 "uniform float4 ScreenCenterRefractReflect,\n"
2187 "uniform float4 RefractColor,\n"
2188 "out float4 gl_FragColor : COLOR\n"
2189 ")\n"
2190 "{\n"
2191 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2192 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2193 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2194 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2195 "       // FIXME temporary hack to detect the case that the reflection\n"
2196 "       // gets blackened at edges due to leaving the area that contains actual\n"
2197 "       // content.\n"
2198 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2199 "       // 'appening.\n"
2200 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2201 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2202 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2203 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2204 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2205 "       gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2206 "}\n"
2207 "#endif\n"
2208 "#else // !MODE_REFRACTION\n"
2209 "\n"
2210 "\n"
2211 "\n"
2212 "\n"
2213 "#ifdef MODE_WATER\n"
2214 "#ifdef VERTEX_SHADER\n"
2215 "\n"
2216 "void main\n"
2217 "(\n"
2218 "float4 gl_Vertex : POSITION,\n"
2219 "uniform float4x4 ModelViewProjectionMatrix,\n"
2220 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2221 "uniform float4x4 TexMatrix,\n"
2222 "uniform float3 EyePosition,\n"
2223 "out float4 gl_Position : POSITION,\n"
2224 "out float2 TexCoord : TEXCOORD0,\n"
2225 "out float3 EyeVector : TEXCOORD1,\n"
2226 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2227 ")\n"
2228 "{\n"
2229 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2230 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2231 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2232 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2233 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2234 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2235 "       ModelViewProjectionPosition = gl_Position;\n"
2236 "}\n"
2237 "#endif\n"
2238 "\n"
2239 "#ifdef FRAGMENT_SHADER\n"
2240 "void main\n"
2241 "(\n"
2242 "float2 TexCoord : TEXCOORD0,\n"
2243 "float3 EyeVector : TEXCOORD1,\n"
2244 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2245 "uniform sampler2D Texture_Normal,\n"
2246 "uniform sampler2D Texture_Refraction,\n"
2247 "uniform sampler2D Texture_Reflection,\n"
2248 "uniform float4 DistortScaleRefractReflect,\n"
2249 "uniform float4 ScreenScaleRefractReflect,\n"
2250 "uniform float4 ScreenCenterRefractReflect,\n"
2251 "uniform float4 RefractColor,\n"
2252 "uniform float4 ReflectColor,\n"
2253 "uniform float ReflectFactor,\n"
2254 "uniform float ReflectOffset,\n"
2255 "out float4 gl_FragColor : COLOR\n"
2256 ")\n"
2257 "{\n"
2258 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2259 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2260 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2261 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2262 "       // FIXME temporary hack to detect the case that the reflection\n"
2263 "       // gets blackened at edges due to leaving the area that contains actual\n"
2264 "       // content.\n"
2265 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2266 "       // 'appening.\n"
2267 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2268 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2269 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2270 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2271 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2272 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2273 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2274 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2275 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2276 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2277 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2278 "       gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2279 "}\n"
2280 "#endif\n"
2281 "#else // !MODE_WATER\n"
2282 "\n"
2283 "\n"
2284 "\n"
2285 "\n"
2286 "// 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"
2287 "\n"
2288 "// fragment shader specific:\n"
2289 "#ifdef FRAGMENT_SHADER\n"
2290 "\n"
2291 "#ifdef USEFOG\n"
2292 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask, sampler2D Texture_FogHeightTexture)\n"
2293 "{\n"
2294 "       float fogfrac;\n"
2295 "#ifdef USEFOGHEIGHTTEXTURE\n"
2296 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2297 "       fogfrac = fogheightpixel.a;\n"
2298 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2299 "#else\n"
2300 "# ifdef USEFOGOUTSIDE\n"
2301 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2302 "# else\n"
2303 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2304 "# endif\n"
2305 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2306 "#endif\n"
2307 "}\n"
2308 "#endif\n"
2309 "\n"
2310 "#ifdef USEOFFSETMAPPING\n"
2311 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2312 "{\n"
2313 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2314 "       // 14 sample relief mapping: linear search and then binary search\n"
2315 "       // this basically steps forward a small amount repeatedly until it finds\n"
2316 "       // itself inside solid, then jitters forward and back using decreasing\n"
2317 "       // amounts to find the impact\n"
2318 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2319 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2320 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2321 "       float3 RT = float3(TexCoord, 1);\n"
2322 "       OffsetVector *= 0.1;\n"
2323 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2324 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2325 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2326 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2327 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2328 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2329 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2330 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2331 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2332 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2333 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2334 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2335 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2336 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2337 "       return RT.xy;\n"
2338 "#else\n"
2339 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2340 "       // this basically moves forward the full distance, and then backs up based\n"
2341 "       // on height of samples\n"
2342 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2343 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2344 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2345 "       TexCoord += OffsetVector;\n"
2346 "       OffsetVector *= 0.333;\n"
2347 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2348 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2349 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2350 "       return TexCoord;\n"
2351 "#endif\n"
2352 "}\n"
2353 "#endif // USEOFFSETMAPPING\n"
2354 "\n"
2355 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2356 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2357 "# ifdef USESHADOWMAPORTHO\n"
2358 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2359 "# else\n"
2360 "#  ifdef USESHADOWMAPVSDCT\n"
2361 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2362 "{\n"
2363 "       float3 adir = abs(dir);\n"
2364 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2365 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2366 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2367 "}\n"
2368 "#  else\n"
2369 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2370 "{\n"
2371 "       float3 adir = abs(dir);\n"
2372 "       float ma = adir.z;\n"
2373 "       float4 proj = float4(dir, 2.5);\n"
2374 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2375 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2376 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2377 "       return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2378 "}\n"
2379 "#  endif\n"
2380 "# endif\n"
2381 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2382 "\n"
2383 "#ifdef USESHADOWMAPCUBE\n"
2384 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2385 "{\n"
2386 "    float3 adir = abs(dir);\n"
2387 "    return float4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
2388 "}\n"
2389 "#endif\n"
2390 "\n"
2391 "# ifdef USESHADOWMAPRECT\n"
2392 "#ifdef USESHADOWMAPVSDCT\n"
2393 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2394 "#else\n"
2395 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2396 "#endif\n"
2397 "{\n"
2398 "#ifdef USESHADOWMAPVSDCT\n"
2399 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2400 "#else\n"
2401 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2402 "#endif\n"
2403 "       float f;\n"
2404 "#  ifdef USESHADOWSAMPLER\n"
2405 "\n"
2406 "#    ifdef USESHADOWMAPPCF\n"
2407 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2408 "    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"
2409 "#    else\n"
2410 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2411 "#    endif\n"
2412 "\n"
2413 "#  else\n"
2414 "\n"
2415 "#    ifdef USESHADOWMAPPCF\n"
2416 "#      if USESHADOWMAPPCF > 1\n"
2417 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2418 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2419 "    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"
2420 "    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"
2421 "    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"
2422 "    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"
2423 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2424 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2425 "#      else\n"
2426 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2427 "    float2 offset = frac(shadowmaptc.xy);\n"
2428 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2429 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2430 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2431 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2432 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2433 "#      endif\n"
2434 "#    else\n"
2435 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2436 "#    endif\n"
2437 "\n"
2438 "#  endif\n"
2439 "#  ifdef USESHADOWMAPORTHO\n"
2440 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2441 "#  else\n"
2442 "       return f;\n"
2443 "#  endif\n"
2444 "}\n"
2445 "# endif\n"
2446 "\n"
2447 "# ifdef USESHADOWMAP2D\n"
2448 "#ifdef USESHADOWMAPVSDCT\n"
2449 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2450 "#else\n"
2451 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2452 "#endif\n"
2453 "{\n"
2454 "#ifdef USESHADOWMAPVSDCT\n"
2455 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2456 "#else\n"
2457 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2458 "#endif\n"
2459 "    float f;\n"
2460 "\n"
2461 "#  ifdef USESHADOWSAMPLER\n"
2462 "#    ifdef USESHADOWMAPPCF\n"
2463 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2464 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2465 "    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"
2466 "#    else\n"
2467 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2468 "#    endif\n"
2469 "#  else\n"
2470 "#    ifdef USESHADOWMAPPCF\n"
2471 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2472 "#      ifdef GL_ARB_texture_gather\n"
2473 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2474 "#      else\n"
2475 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2476 "#      endif\n"
2477 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2478 "    center *= ShadowMap_TextureScale;\n"
2479 "    float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2480 "    float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2481 "    float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2482 "    float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2483 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2484 "                lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2485 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2486 "#     else\n"
2487 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)  \n"
2488 "#      if USESHADOWMAPPCF > 1\n"
2489 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2490 "    center *= ShadowMap_TextureScale;\n"
2491 "    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"
2492 "    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"
2493 "    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"
2494 "    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"
2495 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2496 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2497 "#      else\n"
2498 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2499 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2500 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2501 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2502 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2503 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2504 "#      endif\n"
2505 "#     endif\n"
2506 "#    else\n"
2507 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2508 "#    endif\n"
2509 "#  endif\n"
2510 "#  ifdef USESHADOWMAPORTHO\n"
2511 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2512 "#  else\n"
2513 "       return f;\n"
2514 "#  endif\n"
2515 "}\n"
2516 "# endif\n"
2517 "\n"
2518 "# ifdef USESHADOWMAPCUBE\n"
2519 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2520 "{\n"
2521 "    // apply depth texture cubemap as light filter\n"
2522 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2523 "    float f;\n"
2524 "#  ifdef USESHADOWSAMPLER\n"
2525 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2526 "#  else\n"
2527 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2528 "#  endif\n"
2529 "    return f;\n"
2530 "}\n"
2531 "# endif\n"
2532 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2533 "#endif // FRAGMENT_SHADER\n"
2534 "\n"
2535 "\n"
2536 "\n"
2537 "\n"
2538 "#ifdef MODE_DEFERREDGEOMETRY\n"
2539 "#ifdef VERTEX_SHADER\n"
2540 "void main\n"
2541 "(\n"
2542 "float4 gl_Vertex : POSITION,\n"
2543 "uniform float4x4 ModelViewProjectionMatrix,\n"
2544 "#ifdef USEVERTEXTEXTUREBLEND\n"
2545 "float4 gl_Color : COLOR0,\n"
2546 "#endif\n"
2547 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2548 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2549 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2550 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2551 "uniform float4x4 TexMatrix,\n"
2552 "#ifdef USEVERTEXTEXTUREBLEND\n"
2553 "uniform float4x4 BackgroundTexMatrix,\n"
2554 "#endif\n"
2555 "uniform float4x4 ModelViewMatrix,\n"
2556 "#ifdef USEOFFSETMAPPING\n"
2557 "uniform float3 EyePosition,\n"
2558 "#endif\n"
2559 "out float4 gl_Position : POSITION,\n"
2560 "out float4 gl_FrontColor : COLOR,\n"
2561 "out float4 TexCoordBoth : TEXCOORD0,\n"
2562 "#ifdef USEOFFSETMAPPING\n"
2563 "out float3 EyeVector : TEXCOORD2,\n"
2564 "#endif\n"
2565 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2566 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2567 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2568 ")\n"
2569 "{\n"
2570 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2571 "#ifdef USEVERTEXTEXTUREBLEND\n"
2572 "       gl_FrontColor = gl_Color;\n"
2573 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2574 "#endif\n"
2575 "\n"
2576 "       // transform unnormalized eye direction into tangent space\n"
2577 "#ifdef USEOFFSETMAPPING\n"
2578 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2579 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2580 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2581 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2582 "#endif\n"
2583 "\n"
2584 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2585 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2586 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2587 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2588 "}\n"
2589 "#endif // VERTEX_SHADER\n"
2590 "\n"
2591 "#ifdef FRAGMENT_SHADER\n"
2592 "void main\n"
2593 "(\n"
2594 "float4 TexCoordBoth : TEXCOORD0,\n"
2595 "float3 EyeVector : TEXCOORD2,\n"
2596 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2597 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2598 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2599 "uniform sampler2D Texture_Normal,\n"
2600 "#ifdef USEALPHAKILL\n"
2601 "uniform sampler2D Texture_Color,\n"
2602 "#endif\n"
2603 "uniform sampler2D Texture_Gloss,\n"
2604 "#ifdef USEVERTEXTEXTUREBLEND\n"
2605 "uniform sampler2D Texture_SecondaryNormal,\n"
2606 "uniform sampler2D Texture_SecondaryGloss,\n"
2607 "#endif\n"
2608 "#ifdef USEOFFSETMAPPING\n"
2609 "uniform float OffsetMapping_Scale,\n"
2610 "#endif\n"
2611 "uniform half SpecularPower,\n"
2612 "out float4 gl_FragColor : COLOR\n"
2613 ")\n"
2614 "{\n"
2615 "       float2 TexCoord = TexCoordBoth.xy;\n"
2616 "#ifdef USEOFFSETMAPPING\n"
2617 "       // apply offsetmapping\n"
2618 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2619 "#define TexCoord TexCoordOffset\n"
2620 "#endif\n"
2621 "\n"
2622 "#ifdef USEALPHAKILL\n"
2623 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2624 "               discard;\n"
2625 "#endif\n"
2626 "\n"
2627 "#ifdef USEVERTEXTEXTUREBLEND\n"
2628 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2629 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2630 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2631 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2632 "#endif\n"
2633 "\n"
2634 "#ifdef USEVERTEXTEXTUREBLEND\n"
2635 "       float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2636 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2637 "#else\n"
2638 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2639 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2640 "#endif\n"
2641 "\n"
2642 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2643 "}\n"
2644 "#endif // FRAGMENT_SHADER\n"
2645 "#else // !MODE_DEFERREDGEOMETRY\n"
2646 "\n"
2647 "\n"
2648 "\n"
2649 "\n"
2650 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2651 "#ifdef VERTEX_SHADER\n"
2652 "void main\n"
2653 "(\n"
2654 "float4 gl_Vertex : POSITION,\n"
2655 "uniform float4x4 ModelViewProjectionMatrix,\n"
2656 "uniform float4x4 ModelViewMatrix,\n"
2657 "out float4 gl_Position : POSITION,\n"
2658 "out float4 ModelViewPosition : TEXCOORD0\n"
2659 ")\n"
2660 "{\n"
2661 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2662 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2663 "}\n"
2664 "#endif // VERTEX_SHADER\n"
2665 "\n"
2666 "#ifdef FRAGMENT_SHADER\n"
2667 "void main\n"
2668 "(\n"
2669 "float2 Pixel : WPOS,\n"
2670 "float4 ModelViewPosition : TEXCOORD0,\n"
2671 "uniform float4x4 ViewToLight,\n"
2672 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2673 "uniform float3 LightPosition,\n"
2674 "uniform half2 PixelToScreenTexCoord,\n"
2675 "uniform half3 DeferredColor_Ambient,\n"
2676 "uniform half3 DeferredColor_Diffuse,\n"
2677 "#ifdef USESPECULAR\n"
2678 "uniform half3 DeferredColor_Specular,\n"
2679 "uniform half SpecularPower,\n"
2680 "#endif\n"
2681 "uniform sampler2D Texture_Attenuation,\n"
2682 "uniform sampler2D Texture_ScreenDepth,\n"
2683 "uniform sampler2D Texture_ScreenNormalMap,\n"
2684 "\n"
2685 "#ifdef USECUBEFILTER\n"
2686 "uniform samplerCUBE Texture_Cube,\n"
2687 "#endif\n"
2688 "\n"
2689 "#ifdef USESHADOWMAPRECT\n"
2690 "# ifdef USESHADOWSAMPLER\n"
2691 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2692 "# else\n"
2693 "uniform samplerRECT Texture_ShadowMapRect,\n"
2694 "# endif\n"
2695 "#endif\n"
2696 "\n"
2697 "#ifdef USESHADOWMAP2D\n"
2698 "# ifdef USESHADOWSAMPLER\n"
2699 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2700 "# else\n"
2701 "uniform sampler2D Texture_ShadowMap2D,\n"
2702 "# endif\n"
2703 "#endif\n"
2704 "\n"
2705 "#ifdef USESHADOWMAPVSDCT\n"
2706 "uniform samplerCUBE Texture_CubeProjection,\n"
2707 "#endif\n"
2708 "\n"
2709 "#ifdef USESHADOWMAPCUBE\n"
2710 "# ifdef USESHADOWSAMPLER\n"
2711 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2712 "# else\n"
2713 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2714 "# endif\n"
2715 "#endif\n"
2716 "\n"
2717 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2718 "uniform float2 ShadowMap_TextureScale,\n"
2719 "uniform float4 ShadowMap_Parameters,\n"
2720 "#endif\n"
2721 "\n"
2722 "out float4 gl_FragData0 : COLOR0,\n"
2723 "out float4 gl_FragData1 : COLOR1\n"
2724 ")\n"
2725 "{\n"
2726 "       // calculate viewspace pixel position\n"
2727 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2728 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2729 "       float3 position;\n"
2730 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2731 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2732 "       // decode viewspace pixel normal\n"
2733 "       half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2734 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2735 "       // surfacenormal = pixel normal in viewspace\n"
2736 "       // LightVector = pixel to light in viewspace\n"
2737 "       // CubeVector = position in lightspace\n"
2738 "       // eyevector = pixel to view in viewspace\n"
2739 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2740 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2741 "#ifdef USEDIFFUSE\n"
2742 "       // calculate diffuse shading\n"
2743 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2744 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2745 "#endif\n"
2746 "#ifdef USESPECULAR\n"
2747 "       // calculate directional shading\n"
2748 "       float3 eyevector = position * -1.0;\n"
2749 "#  ifdef USEEXACTSPECULARMATH\n"
2750 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2751 "#  else\n"
2752 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2753 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2754 "#  endif\n"
2755 "#endif\n"
2756 "\n"
2757 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2758 "       fade *= ShadowMapCompare(CubeVector,\n"
2759 "# if defined(USESHADOWMAP2D)\n"
2760 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2761 "# endif\n"
2762 "# if defined(USESHADOWMAPRECT)\n"
2763 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2764 "# endif\n"
2765 "# if defined(USESHADOWMAPCUBE)\n"
2766 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2767 "# endif\n"
2768 "\n"
2769 "#ifdef USESHADOWMAPVSDCT\n"
2770 ", Texture_CubeProjection\n"
2771 "#endif\n"
2772 "       );\n"
2773 "#endif\n"
2774 "\n"
2775 "#ifdef USEDIFFUSE\n"
2776 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2777 "#else\n"
2778 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2779 "#endif\n"
2780 "#ifdef USESPECULAR\n"
2781 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2782 "#else\n"
2783 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2784 "#endif\n"
2785 "\n"
2786 "# ifdef USECUBEFILTER\n"
2787 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2788 "       gl_FragData0.rgb *= cubecolor;\n"
2789 "       gl_FragData1.rgb *= cubecolor;\n"
2790 "# endif\n"
2791 "}\n"
2792 "#endif // FRAGMENT_SHADER\n"
2793 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2794 "\n"
2795 "\n"
2796 "\n"
2797 "\n"
2798 "#ifdef VERTEX_SHADER\n"
2799 "void main\n"
2800 "(\n"
2801 "float4 gl_Vertex : POSITION,\n"
2802 "uniform float4x4 ModelViewProjectionMatrix,\n"
2803 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2804 "float4 gl_Color : COLOR0,\n"
2805 "#endif\n"
2806 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2807 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2808 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2809 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2810 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2811 "\n"
2812 "uniform float3 EyePosition,\n"
2813 "uniform float4x4 TexMatrix,\n"
2814 "#ifdef USEVERTEXTEXTUREBLEND\n"
2815 "uniform float4x4 BackgroundTexMatrix,\n"
2816 "#endif\n"
2817 "#ifdef MODE_LIGHTSOURCE\n"
2818 "uniform float4x4 ModelToLight,\n"
2819 "#endif\n"
2820 "#ifdef MODE_LIGHTSOURCE\n"
2821 "uniform float3 LightPosition,\n"
2822 "#endif\n"
2823 "#ifdef MODE_LIGHTDIRECTION\n"
2824 "uniform float3 LightDir,\n"
2825 "#endif\n"
2826 "uniform float4 FogPlane,\n"
2827 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2828 "uniform float3 LightPosition,\n"
2829 "#endif\n"
2830 "#ifdef USESHADOWMAPORTHO\n"
2831 "uniform float4x4 ShadowMapMatrix,\n"
2832 "#endif\n"
2833 "\n"
2834 "out float4 gl_FrontColor : COLOR,\n"
2835 "out float4 TexCoordBoth : TEXCOORD0,\n"
2836 "#ifdef USELIGHTMAP\n"
2837 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2838 "#endif\n"
2839 "#ifdef USEEYEVECTOR\n"
2840 "out float3 EyeVector : TEXCOORD2,\n"
2841 "#endif\n"
2842 "#ifdef USEREFLECTION\n"
2843 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2844 "#endif\n"
2845 "#ifdef USEFOG\n"
2846 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2847 "#endif\n"
2848 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2849 "out float3 LightVector : TEXCOORD1,\n"
2850 "#endif\n"
2851 "#ifdef MODE_LIGHTSOURCE\n"
2852 "out float3 CubeVector : TEXCOORD3,\n"
2853 "#endif\n"
2854 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2855 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2856 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2857 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2858 "#endif\n"
2859 "#ifdef USESHADOWMAPORTHO\n"
2860 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2861 "#endif\n"
2862 "out float4 gl_Position : POSITION\n"
2863 ")\n"
2864 "{\n"
2865 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2866 "       gl_FrontColor = gl_Color;\n"
2867 "#endif\n"
2868 "       // copy the surface texcoord\n"
2869 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2870 "#ifdef USEVERTEXTEXTUREBLEND\n"
2871 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2872 "#endif\n"
2873 "#ifdef USELIGHTMAP\n"
2874 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2875 "#endif\n"
2876 "\n"
2877 "#ifdef MODE_LIGHTSOURCE\n"
2878 "       // transform vertex position into light attenuation/cubemap space\n"
2879 "       // (-1 to +1 across the light box)\n"
2880 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2881 "\n"
2882 "# ifdef USEDIFFUSE\n"
2883 "       // transform unnormalized light direction into tangent space\n"
2884 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2885 "       //  normalize it per pixel)\n"
2886 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2887 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2888 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2889 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2890 "# endif\n"
2891 "#endif\n"
2892 "\n"
2893 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2894 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2895 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2896 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2897 "#endif\n"
2898 "\n"
2899 "       // transform unnormalized eye direction into tangent space\n"
2900 "#ifdef USEEYEVECTOR\n"
2901 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2902 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2903 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2904 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2905 "#endif\n"
2906 "\n"
2907 "#ifdef USEFOG\n"
2908 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2909 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2910 "#endif\n"
2911 "\n"
2912 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2913 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2914 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2915 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2916 "#endif\n"
2917 "\n"
2918 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2919 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2920 "\n"
2921 "#ifdef USESHADOWMAPORTHO\n"
2922 "       ShadowMapTC = float3(mul(ShadowMapMatrix, gl_Position));\n"
2923 "#endif\n"
2924 "\n"
2925 "#ifdef USEREFLECTION\n"
2926 "       ModelViewProjectionPosition = gl_Position;\n"
2927 "#endif\n"
2928 "}\n"
2929 "#endif // VERTEX_SHADER\n"
2930 "\n"
2931 "\n"
2932 "\n"
2933 "\n"
2934 "#ifdef FRAGMENT_SHADER\n"
2935 "void main\n"
2936 "(\n"
2937 "#ifdef USEDEFERREDLIGHTMAP\n"
2938 "float2 Pixel : WPOS,\n"
2939 "#endif\n"
2940 "float4 gl_FrontColor : COLOR,\n"
2941 "float4 TexCoordBoth : TEXCOORD0,\n"
2942 "#ifdef USELIGHTMAP\n"
2943 "float2 TexCoordLightmap : TEXCOORD1,\n"
2944 "#endif\n"
2945 "#ifdef USEEYEVECTOR\n"
2946 "float3 EyeVector : TEXCOORD2,\n"
2947 "#endif\n"
2948 "#ifdef USEREFLECTION\n"
2949 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2950 "#endif\n"
2951 "#ifdef USEFOG\n"
2952 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2953 "#endif\n"
2954 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2955 "float3 LightVector : TEXCOORD1,\n"
2956 "#endif\n"
2957 "#ifdef MODE_LIGHTSOURCE\n"
2958 "float3 CubeVector : TEXCOORD3,\n"
2959 "#endif\n"
2960 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2961 "float4 ModelViewPosition : TEXCOORD0,\n"
2962 "#endif\n"
2963 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2964 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2965 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2966 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2967 "#endif\n"
2968 "#ifdef USESHADOWMAPORTHO\n"
2969 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2970 "#endif\n"
2971 "\n"
2972 "uniform sampler2D Texture_Normal,\n"
2973 "uniform sampler2D Texture_Color,\n"
2974 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2975 "uniform sampler2D Texture_Gloss,\n"
2976 "#endif\n"
2977 "#ifdef USEGLOW\n"
2978 "uniform sampler2D Texture_Glow,\n"
2979 "#endif\n"
2980 "#ifdef USEVERTEXTEXTUREBLEND\n"
2981 "uniform sampler2D Texture_SecondaryNormal,\n"
2982 "uniform sampler2D Texture_SecondaryColor,\n"
2983 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2984 "uniform sampler2D Texture_SecondaryGloss,\n"
2985 "#endif\n"
2986 "#ifdef USEGLOW\n"
2987 "uniform sampler2D Texture_SecondaryGlow,\n"
2988 "#endif\n"
2989 "#endif\n"
2990 "#ifdef USECOLORMAPPING\n"
2991 "uniform sampler2D Texture_Pants,\n"
2992 "uniform sampler2D Texture_Shirt,\n"
2993 "#endif\n"
2994 "#ifdef USEFOG\n"
2995 "uniform sampler2D Texture_FogHeightTexture,\n"
2996 "uniform sampler2D Texture_FogMask,\n"
2997 "#endif\n"
2998 "#ifdef USELIGHTMAP\n"
2999 "uniform sampler2D Texture_Lightmap,\n"
3000 "#endif\n"
3001 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
3002 "uniform sampler2D Texture_Deluxemap,\n"
3003 "#endif\n"
3004 "#ifdef USEREFLECTION\n"
3005 "uniform sampler2D Texture_Reflection,\n"
3006 "#endif\n"
3007 "\n"
3008 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3009 "uniform sampler2D Texture_ScreenDepth,\n"
3010 "uniform sampler2D Texture_ScreenNormalMap,\n"
3011 "#endif\n"
3012 "#ifdef USEDEFERREDLIGHTMAP\n"
3013 "uniform sampler2D Texture_ScreenDiffuse,\n"
3014 "uniform sampler2D Texture_ScreenSpecular,\n"
3015 "#endif\n"
3016 "\n"
3017 "#ifdef USECOLORMAPPING\n"
3018 "uniform half3 Color_Pants,\n"
3019 "uniform half3 Color_Shirt,\n"
3020 "#endif\n"
3021 "#ifdef USEFOG\n"
3022 "uniform float3 FogColor,\n"
3023 "uniform float FogRangeRecip,\n"
3024 "uniform float FogPlaneViewDist,\n"
3025 "uniform float FogHeightFade,\n"
3026 "#endif\n"
3027 "\n"
3028 "#ifdef USEOFFSETMAPPING\n"
3029 "uniform float OffsetMapping_Scale,\n"
3030 "#endif\n"
3031 "\n"
3032 "#ifdef USEDEFERREDLIGHTMAP\n"
3033 "uniform half2 PixelToScreenTexCoord,\n"
3034 "uniform half3 DeferredMod_Diffuse,\n"
3035 "uniform half3 DeferredMod_Specular,\n"
3036 "#endif\n"
3037 "uniform half3 Color_Ambient,\n"
3038 "uniform half3 Color_Diffuse,\n"
3039 "uniform half3 Color_Specular,\n"
3040 "uniform half SpecularPower,\n"
3041 "#ifdef USEGLOW\n"
3042 "uniform half3 Color_Glow,\n"
3043 "#endif\n"
3044 "uniform half Alpha,\n"
3045 "#ifdef USEREFLECTION\n"
3046 "uniform float4 DistortScaleRefractReflect,\n"
3047 "uniform float4 ScreenScaleRefractReflect,\n"
3048 "uniform float4 ScreenCenterRefractReflect,\n"
3049 "uniform half4 ReflectColor,\n"
3050 "#endif\n"
3051 "#ifdef USEREFLECTCUBE\n"
3052 "uniform float4x4 ModelToReflectCube,\n"
3053 "uniform sampler2D Texture_ReflectMask,\n"
3054 "uniform samplerCUBE Texture_ReflectCube,\n"
3055 "#endif\n"
3056 "#ifdef MODE_LIGHTDIRECTION\n"
3057 "uniform half3 LightColor,\n"
3058 "#endif\n"
3059 "#ifdef MODE_LIGHTSOURCE\n"
3060 "uniform half3 LightColor,\n"
3061 "#endif\n"
3062 "\n"
3063 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3064 "uniform sampler2D Texture_Attenuation,\n"
3065 "uniform samplerCUBE Texture_Cube,\n"
3066 "#endif\n"
3067 "\n"
3068 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3069 "\n"
3070 "#ifdef USESHADOWMAPRECT\n"
3071 "# ifdef USESHADOWSAMPLER\n"
3072 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
3073 "# else\n"
3074 "uniform samplerRECT Texture_ShadowMapRect,\n"
3075 "# endif\n"
3076 "#endif\n"
3077 "\n"
3078 "#ifdef USESHADOWMAP2D\n"
3079 "# ifdef USESHADOWSAMPLER\n"
3080 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
3081 "# else\n"
3082 "uniform sampler2D Texture_ShadowMap2D,\n"
3083 "# endif\n"
3084 "#endif\n"
3085 "\n"
3086 "#ifdef USESHADOWMAPVSDCT\n"
3087 "uniform samplerCUBE Texture_CubeProjection,\n"
3088 "#endif\n"
3089 "\n"
3090 "#ifdef USESHADOWMAPCUBE\n"
3091 "# ifdef USESHADOWSAMPLER\n"
3092 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
3093 "# else\n"
3094 "uniform samplerCUBE Texture_ShadowMapCube,\n"
3095 "# endif\n"
3096 "#endif\n"
3097 "\n"
3098 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
3099 "uniform float2 ShadowMap_TextureScale,\n"
3100 "uniform float4 ShadowMap_Parameters,\n"
3101 "#endif\n"
3102 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3103 "\n"
3104 "out float4 gl_FragColor : COLOR\n"
3105 ")\n"
3106 "{\n"
3107 "       float2 TexCoord = TexCoordBoth.xy;\n"
3108 "#ifdef USEVERTEXTEXTUREBLEND\n"
3109 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3110 "#endif\n"
3111 "#ifdef USEOFFSETMAPPING\n"
3112 "       // apply offsetmapping\n"
3113 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3114 "#define TexCoord TexCoordOffset\n"
3115 "#endif\n"
3116 "\n"
3117 "       // combine the diffuse textures (base, pants, shirt)\n"
3118 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3119 "#ifdef USEALPHAKILL\n"
3120 "       if (color.a < 0.5)\n"
3121 "               discard;\n"
3122 "#endif\n"
3123 "       color.a *= Alpha;\n"
3124 "#ifdef USECOLORMAPPING\n"
3125 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
3126 "#endif\n"
3127 "#ifdef USEVERTEXTEXTUREBLEND\n"
3128 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3129 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3130 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3131 "       color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
3132 "       color.a = 1.0;\n"
3133 "       //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
3134 "#endif\n"
3135 "\n"
3136 "       // get the surface normal\n"
3137 "#ifdef USEVERTEXTEXTUREBLEND\n"
3138 "       half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3139 "#else\n"
3140 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
3141 "#endif\n"
3142 "\n"
3143 "       // get the material colors\n"
3144 "       half3 diffusetex = color.rgb;\n"
3145 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3146 "# ifdef USEVERTEXTEXTUREBLEND\n"
3147 "       half4 glosstex = half4(lerp(float4(tex2D(Texture_SecondaryGloss, TexCoord2)), float4(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
3148 "# else\n"
3149 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3150 "# endif\n"
3151 "#endif\n"
3152 "\n"
3153 "#ifdef USEREFLECTCUBE\n"
3154 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3155 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3156 "       float3 ReflectCubeTexCoord = float3(mul(ModelToReflectCube, float4(ModelReflectVector, 0)));\n"
3157 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord)) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord));\n"
3158 "#endif\n"
3159 "\n"
3160 "\n"
3161 "\n"
3162 "\n"
3163 "#ifdef MODE_LIGHTSOURCE\n"
3164 "       // light source\n"
3165 "#ifdef USEDIFFUSE\n"
3166 "       half3 lightnormal = half3(normalize(LightVector));\n"
3167 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3168 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3169 "#ifdef USESPECULAR\n"
3170 "#ifdef USEEXACTSPECULARMATH\n"
3171 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3172 "#else\n"
3173 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3174 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3175 "#endif\n"
3176 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3177 "#endif\n"
3178 "#else\n"
3179 "       color.rgb = diffusetex * Color_Ambient;\n"
3180 "#endif\n"
3181 "       color.rgb *= LightColor;\n"
3182 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
3183 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3184 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
3185 "# if defined(USESHADOWMAP2D)\n"
3186 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3187 "# endif\n"
3188 "# if defined(USESHADOWMAPRECT)\n"
3189 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3190 "# endif\n"
3191 "# if defined(USESHADOWMAPCUBE)\n"
3192 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3193 "# endif\n"
3194 "\n"
3195 "#ifdef USESHADOWMAPVSDCT\n"
3196 ", Texture_CubeProjection\n"
3197 "#endif\n"
3198 "       );\n"
3199 "\n"
3200 "#endif\n"
3201 "# ifdef USECUBEFILTER\n"
3202 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
3203 "# endif\n"
3204 "#endif // MODE_LIGHTSOURCE\n"
3205 "\n"
3206 "\n"
3207 "\n"
3208 "\n"
3209 "#ifdef MODE_LIGHTDIRECTION\n"
3210 "#define SHADING\n"
3211 "#ifdef USEDIFFUSE\n"
3212 "       half3 lightnormal = half3(normalize(LightVector));\n"
3213 "#endif\n"
3214 "#define lightcolor LightColor\n"
3215 "#endif // MODE_LIGHTDIRECTION\n"
3216 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3217 "#define SHADING\n"
3218 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3219 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3220 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3221 "       // convert modelspace light vector to tangentspace\n"
3222 "       half3 lightnormal;\n"
3223 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3224 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3225 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3226 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3227 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3228 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3229 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3230 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3231 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3232 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3233 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3234 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3235 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3236 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3237 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3238 "#define SHADING\n"
3239 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3240 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3241 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3242 "#endif\n"
3243 "\n"
3244 "\n"
3245 "\n"
3246 "\n"
3247 "#ifdef MODE_FAKELIGHT\n"
3248 "#define SHADING\n"
3249 "half3 lightnormal = half3(normalize(EyeVector));\n"
3250 "half3 lightcolor = half3(1.0);\n"
3251 "#endif // MODE_FAKELIGHT\n"
3252 "\n"
3253 "\n"
3254 "\n"
3255 "\n"
3256 "#ifdef MODE_LIGHTMAP\n"
3257 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3258 "#endif // MODE_LIGHTMAP\n"
3259 "#ifdef MODE_VERTEXCOLOR\n"
3260 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3261 "#endif // MODE_VERTEXCOLOR\n"
3262 "#ifdef MODE_FLATCOLOR\n"
3263 "       color.rgb = diffusetex * Color_Ambient;\n"
3264 "#endif // MODE_FLATCOLOR\n"
3265 "\n"
3266 "\n"
3267 "\n"
3268 "\n"
3269 "#ifdef SHADING\n"
3270 "# ifdef USEDIFFUSE\n"
3271 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3272 "#  ifdef USESPECULAR\n"
3273 "#   ifdef USEEXACTSPECULARMATH\n"
3274 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3275 "#   else\n"
3276 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3277 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3278 "#   endif\n"
3279 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3280 "#  else\n"
3281 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3282 "#  endif\n"
3283 "# else\n"
3284 "       color.rgb = diffusetex * Color_Ambient;\n"
3285 "# endif\n"
3286 "#endif\n"
3287 "\n"
3288 "#ifdef USESHADOWMAPORTHO\n"
3289 "       color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3290 "# if defined(USESHADOWMAP2D)\n"
3291 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3292 "# endif\n"
3293 "# if defined(USESHADOWMAPRECT)\n"
3294 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3295 "# endif\n"
3296 "       );\n"
3297 "#endif\n"
3298 "\n"
3299 "#ifdef USEDEFERREDLIGHTMAP\n"
3300 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3301 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3302 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3303 "#endif\n"
3304 "\n"
3305 "#ifdef USEGLOW\n"
3306 "#ifdef USEVERTEXTEXTUREBLEND\n"
3307 "       color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3308 "#else\n"
3309 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3310 "#endif\n"
3311 "#endif\n"
3312 "\n"
3313 "#ifdef USEFOG\n"
3314 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3315 "#endif\n"
3316 "\n"
3317 "       // 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"
3318 "#ifdef USEREFLECTION\n"
3319 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3320 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3321 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3322 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3323 "       // FIXME temporary hack to detect the case that the reflection\n"
3324 "       // gets blackened at edges due to leaving the area that contains actual\n"
3325 "       // content.\n"
3326 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3327 "       // 'appening.\n"
3328 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3329 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3330 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3331 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3332 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3333 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3334 "#endif\n"
3335 "\n"
3336 "       gl_FragColor = float4(color);\n"
3337 "}\n"
3338 "#endif // FRAGMENT_SHADER\n"
3339 "\n"
3340 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3341 "#endif // !MODE_DEFERREDGEOMETRY\n"
3342 "#endif // !MODE_WATER\n"
3343 "#endif // !MODE_REFRACTION\n"
3344 "#endif // !MODE_BLOOMBLUR\n"
3345 "#endif // !MODE_GENERIC\n"
3346 "#endif // !MODE_POSTPROCESS\n"
3347 "#endif // !MODE_SHOWDEPTH\n"
3348 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3349 ;
3350
3351 char *glslshaderstring = NULL;
3352 char *cgshaderstring = NULL;
3353
3354 //=======================================================================================================================================================
3355
3356 typedef struct shaderpermutationinfo_s
3357 {
3358         const char *pretext;
3359         const char *name;
3360 }
3361 shaderpermutationinfo_t;
3362
3363 typedef struct shadermodeinfo_s
3364 {
3365         const char *vertexfilename;
3366         const char *geometryfilename;
3367         const char *fragmentfilename;
3368         const char *pretext;
3369         const char *name;
3370 }
3371 shadermodeinfo_t;
3372
3373 typedef enum shaderpermutation_e
3374 {
3375         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3376         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3377         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3378         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3379         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3380         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3381         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3382         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3383         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3384         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3385         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3386         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3387         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3388         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3389         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3390         SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3391         SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3392         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3393         SHADERPERMUTATION_SHADOWMAPRECT = 1<<18, ///< (lightsource) use shadowmap rectangle texture as light filter
3394         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<19, ///< (lightsource) use shadowmap cubemap texture as light filter
3395         SHADERPERMUTATION_SHADOWMAP2D = 1<<20, ///< (lightsource) use shadowmap rectangle texture as light filter
3396         SHADERPERMUTATION_SHADOWMAPPCF = 1<<21, ///< (lightsource) use percentage closer filtering on shadowmap test results
3397         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<22, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3398         SHADERPERMUTATION_SHADOWSAMPLER = 1<<23, ///< (lightsource) use hardware shadowmap test
3399         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<24, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3400         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<25, //< (lightsource) use orthographic shadowmap projection
3401         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<26, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3402         SHADERPERMUTATION_ALPHAKILL = 1<<27, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3403         SHADERPERMUTATION_REFLECTCUBE = 1<<28, ///< fake reflections using global cubemap (not HDRI light probe)
3404         SHADERPERMUTATION_NORMALMAPSCROLLBLEND = 1<<29, // (water) counter-direction normalmaps scrolling
3405         SHADERPERMUTATION_LIMIT = 1<<30, ///< size of permutations array
3406         SHADERPERMUTATION_COUNT = 30 ///< size of shaderpermutationinfo array
3407 }
3408 shaderpermutation_t;
3409
3410 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3411 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3412 {
3413         {"#define USEDIFFUSE\n", " diffuse"},
3414         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3415         {"#define USEVIEWTINT\n", " viewtint"},
3416         {"#define USECOLORMAPPING\n", " colormapping"},
3417         {"#define USESATURATION\n", " saturation"},
3418         {"#define USEFOGINSIDE\n", " foginside"},
3419         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3420         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3421         {"#define USEGAMMARAMPS\n", " gammaramps"},
3422         {"#define USECUBEFILTER\n", " cubefilter"},
3423         {"#define USEGLOW\n", " glow"},
3424         {"#define USEBLOOM\n", " bloom"},
3425         {"#define USESPECULAR\n", " specular"},
3426         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3427         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3428         {"#define USEREFLECTION\n", " reflection"},
3429         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3430         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3431         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3432         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3433         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3434         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3435         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3436         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3437         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3438         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3439         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3440         {"#define USEALPHAKILL\n", " alphakill"},
3441         {"#define USEREFLECTCUBE\n", " reflectcube"},
3442         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3443 };
3444
3445 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3446 typedef enum shadermode_e
3447 {
3448         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3449         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3450         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3451         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3452         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3453         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3454         SHADERMODE_FAKELIGHT, ///< (fakelight) modulate texture by "fake" lighting (no lightmaps, no nothing)
3455         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3456         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3457         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3458         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3459         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3460         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3461         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3462         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3463         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3464         SHADERMODE_COUNT
3465 }
3466 shadermode_t;
3467
3468 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3469 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3470 {
3471         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3472         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3473         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3474         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3475         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3476         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3477         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3478         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3479         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3480         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3481         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3482         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3483         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3484         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3485         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3486         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3487 };
3488
3489 #ifdef SUPPORTCG
3490 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3491 {
3492         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3493         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3494         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3495         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3496         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3497         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3498         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
3499         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3500         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3501         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3502         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3503         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3504         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3505         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3506         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3507         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3508 };
3509 #endif
3510
3511 struct r_glsl_permutation_s;
3512 typedef struct r_glsl_permutation_s
3513 {
3514         /// hash lookup data
3515         struct r_glsl_permutation_s *hashnext;
3516         unsigned int mode;
3517         unsigned int permutation;
3518
3519         /// indicates if we have tried compiling this permutation already
3520         qboolean compiled;
3521         /// 0 if compilation failed
3522         int program;
3523         /// locations of detected uniforms in program object, or -1 if not found
3524         int loc_Texture_First;
3525         int loc_Texture_Second;
3526         int loc_Texture_GammaRamps;
3527         int loc_Texture_Normal;
3528         int loc_Texture_Color;
3529         int loc_Texture_Gloss;
3530         int loc_Texture_Glow;
3531         int loc_Texture_SecondaryNormal;
3532         int loc_Texture_SecondaryColor;
3533         int loc_Texture_SecondaryGloss;
3534         int loc_Texture_SecondaryGlow;
3535         int loc_Texture_Pants;
3536         int loc_Texture_Shirt;
3537         int loc_Texture_FogHeightTexture;
3538         int loc_Texture_FogMask;
3539         int loc_Texture_Lightmap;
3540         int loc_Texture_Deluxemap;
3541         int loc_Texture_Attenuation;
3542         int loc_Texture_Cube;
3543         int loc_Texture_Refraction;
3544         int loc_Texture_Reflection;
3545         int loc_Texture_ShadowMapRect;
3546         int loc_Texture_ShadowMapCube;
3547         int loc_Texture_ShadowMap2D;
3548         int loc_Texture_CubeProjection;
3549         int loc_Texture_ScreenDepth;
3550         int loc_Texture_ScreenNormalMap;
3551         int loc_Texture_ScreenDiffuse;
3552         int loc_Texture_ScreenSpecular;
3553         int loc_Texture_ReflectMask;
3554         int loc_Texture_ReflectCube;
3555         int loc_Alpha;
3556         int loc_BloomBlur_Parameters;
3557         int loc_ClientTime;
3558         int loc_Color_Ambient;
3559         int loc_Color_Diffuse;
3560         int loc_Color_Specular;
3561         int loc_Color_Glow;
3562         int loc_Color_Pants;
3563         int loc_Color_Shirt;
3564         int loc_DeferredColor_Ambient;
3565         int loc_DeferredColor_Diffuse;
3566         int loc_DeferredColor_Specular;
3567         int loc_DeferredMod_Diffuse;
3568         int loc_DeferredMod_Specular;
3569         int loc_DistortScaleRefractReflect;
3570         int loc_EyePosition;
3571         int loc_FogColor;
3572         int loc_FogHeightFade;
3573         int loc_FogPlane;
3574         int loc_FogPlaneViewDist;
3575         int loc_FogRangeRecip;
3576         int loc_LightColor;
3577         int loc_LightDir;
3578         int loc_LightPosition;
3579         int loc_OffsetMapping_Scale;
3580         int loc_PixelSize;
3581         int loc_ReflectColor;
3582         int loc_ReflectFactor;
3583         int loc_ReflectOffset;
3584         int loc_RefractColor;
3585         int loc_Saturation;
3586         int loc_ScreenCenterRefractReflect;
3587         int loc_ScreenScaleRefractReflect;
3588         int loc_ScreenToDepth;
3589         int loc_ShadowMap_Parameters;
3590         int loc_ShadowMap_TextureScale;
3591         int loc_SpecularPower;
3592         int loc_UserVec1;
3593         int loc_UserVec2;
3594         int loc_UserVec3;
3595         int loc_UserVec4;
3596         int loc_ViewTintColor;
3597         int loc_ViewToLight;
3598         int loc_ModelToLight;
3599         int loc_TexMatrix;
3600         int loc_BackgroundTexMatrix;
3601         int loc_ModelViewProjectionMatrix;
3602         int loc_ModelViewMatrix;
3603         int loc_PixelToScreenTexCoord;
3604         int loc_ModelToReflectCube;
3605         int loc_ShadowMapMatrix;        
3606         int loc_NormalmapScrollBlend;
3607 }
3608 r_glsl_permutation_t;
3609
3610 #define SHADERPERMUTATION_HASHSIZE 256
3611
3612 /// information about each possible shader permutation
3613 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3614 /// currently selected permutation
3615 r_glsl_permutation_t *r_glsl_permutation;
3616 /// storage for permutations linked in the hash table
3617 memexpandablearray_t r_glsl_permutationarray;
3618
3619 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3620 {
3621         //unsigned int hashdepth = 0;
3622         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3623         r_glsl_permutation_t *p;
3624         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3625         {
3626                 if (p->mode == mode && p->permutation == permutation)
3627                 {
3628                         //if (hashdepth > 10)
3629                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3630                         return p;
3631                 }
3632                 //hashdepth++;
3633         }
3634         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3635         p->mode = mode;
3636         p->permutation = permutation;
3637         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3638         r_glsl_permutationhash[mode][hashindex] = p;
3639         //if (hashdepth > 10)
3640         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3641         return p;
3642 }
3643
3644 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3645 {
3646         char *shaderstring;
3647         if (!filename || !filename[0])
3648                 return NULL;
3649         if (!strcmp(filename, "glsl/default.glsl"))
3650         {
3651                 if (!glslshaderstring)
3652                 {
3653                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3654                         if (glslshaderstring)
3655                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3656                         else
3657                                 glslshaderstring = (char *)builtinshaderstring;
3658                 }
3659                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3660                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3661                 return shaderstring;
3662         }
3663         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3664         if (shaderstring)
3665         {
3666                 if (printfromdisknotice)
3667                         Con_DPrintf("from disk %s... ", filename);
3668                 return shaderstring;
3669         }
3670         return shaderstring;
3671 }
3672
3673 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3674 {
3675         int i;
3676         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3677         int vertstrings_count = 0;
3678         int geomstrings_count = 0;
3679         int fragstrings_count = 0;
3680         char *vertexstring, *geometrystring, *fragmentstring;
3681         const char *vertstrings_list[32+3];
3682         const char *geomstrings_list[32+3];
3683         const char *fragstrings_list[32+3];
3684         char permutationname[256];
3685
3686         if (p->compiled)
3687                 return;
3688         p->compiled = true;
3689         p->program = 0;
3690
3691         permutationname[0] = 0;
3692         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3693         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3694         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3695
3696         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3697
3698         // the first pretext is which type of shader to compile as
3699         // (later these will all be bound together as a program object)
3700         vertstrings_count = 0;
3701         geomstrings_count = 0;
3702         fragstrings_count = 0;
3703         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3704         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3705         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3706
3707         // the second pretext is the mode (for example a light source)
3708         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3709         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3710         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3711         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3712
3713         // now add all the permutation pretexts
3714         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3715         {
3716                 if (permutation & (1<<i))
3717                 {
3718                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3719                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3720                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3721                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3722                 }
3723                 else
3724                 {
3725                         // keep line numbers correct
3726                         vertstrings_list[vertstrings_count++] = "\n";
3727                         geomstrings_list[geomstrings_count++] = "\n";
3728                         fragstrings_list[fragstrings_count++] = "\n";
3729                 }
3730         }
3731
3732         // now append the shader text itself
3733         vertstrings_list[vertstrings_count++] = vertexstring;
3734         geomstrings_list[geomstrings_count++] = geometrystring;
3735         fragstrings_list[fragstrings_count++] = fragmentstring;
3736
3737         // if any sources were NULL, clear the respective list
3738         if (!vertexstring)
3739                 vertstrings_count = 0;
3740         if (!geometrystring)
3741                 geomstrings_count = 0;
3742         if (!fragmentstring)
3743                 fragstrings_count = 0;
3744
3745         // compile the shader program
3746         if (vertstrings_count + geomstrings_count + fragstrings_count)
3747                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3748         if (p->program)
3749         {
3750                 CHECKGLERROR
3751                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3752                 // look up all the uniform variable names we care about, so we don't
3753                 // have to look them up every time we set them
3754
3755                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3756                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3757                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3758                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3759                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3760                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3761                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3762                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3763                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3764                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3765                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3766                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3767                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3768                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3769                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3770                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3771                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3772                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3773                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3774                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3775                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3776                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3777                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3778                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3779                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3780                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3781                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3782                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3783                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3784                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3785                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3786                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3787                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3788                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3789                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3790                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3791                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3792                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3793                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3794                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3795                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3796                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3797                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3798                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3799                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3800                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3801                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3802                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3803                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3804                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3805                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3806                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3807                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3808                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3809                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3810                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3811                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3812                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3813                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3814                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3815                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3816                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3817                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3818                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3819                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3820                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3821                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3822                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3823                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3824                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3825                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3826                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3827                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3828                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3829                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3830                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3831                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3832                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3833                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3834                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3835                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3836                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");            
3837                 p->loc_NormalmapScrollBlend       = qglGetUniformLocationARB(p->program, "NormalmapScrollBlend");
3838                 // initialize the samplers to refer to the texture units we use
3839                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3840                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3841                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3842                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3843                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3844                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3845                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3846                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3847                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3848                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3849                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3850                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3851                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3852                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3853                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3854                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3855                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3856                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3857                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3858                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3859                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3860                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
3861                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3862                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3863                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3864                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3865                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3866                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3867                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3868                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3869                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3870                 CHECKGLERROR
3871                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3872         }
3873         else
3874                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3875
3876         // free the strings
3877         if (vertexstring)
3878                 Mem_Free(vertexstring);
3879         if (geometrystring)
3880                 Mem_Free(geometrystring);
3881         if (fragmentstring)
3882                 Mem_Free(fragmentstring);
3883 }
3884
3885 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3886 {
3887         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3888         if (r_glsl_permutation != perm)
3889         {
3890                 r_glsl_permutation = perm;
3891                 if (!r_glsl_permutation->program)
3892                 {
3893                         if (!r_glsl_permutation->compiled)
3894                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3895                         if (!r_glsl_permutation->program)
3896                         {
3897                                 // remove features until we find a valid permutation
3898                                 int i;
3899                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3900                                 {
3901                                         // reduce i more quickly whenever it would not remove any bits
3902                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3903                                         if (!(permutation & j))
3904                                                 continue;
3905                                         permutation -= j;
3906                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3907                                         if (!r_glsl_permutation->compiled)
3908                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3909                                         if (r_glsl_permutation->program)
3910                                                 break;
3911                                 }
3912                                 if (i >= SHADERPERMUTATION_COUNT)
3913                                 {
3914                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3915                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3916                                         qglUseProgramObjectARB(0);CHECKGLERROR
3917                                         return; // no bit left to clear, entire mode is broken
3918                                 }
3919                         }
3920                 }
3921                 CHECKGLERROR
3922                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3923         }
3924         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3925         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3926         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3927 }
3928
3929 #ifdef SUPPORTCG
3930 #include <Cg/cgGL.h>
3931 struct r_cg_permutation_s;
3932 typedef struct r_cg_permutation_s
3933 {
3934         /// hash lookup data
3935         struct r_cg_permutation_s *hashnext;
3936         unsigned int mode;
3937         unsigned int permutation;
3938
3939         /// indicates if we have tried compiling this permutation already
3940         qboolean compiled;
3941         /// 0 if compilation failed
3942         CGprogram vprogram;
3943         CGprogram fprogram;
3944         /// locations of detected parameters in programs, or NULL if not found
3945         CGparameter vp_EyePosition;
3946         CGparameter vp_FogPlane;
3947         CGparameter vp_LightDir;
3948         CGparameter vp_LightPosition;
3949         CGparameter vp_ModelToLight;
3950         CGparameter vp_TexMatrix;
3951         CGparameter vp_BackgroundTexMatrix;
3952         CGparameter vp_ModelViewProjectionMatrix;
3953         CGparameter vp_ModelViewMatrix;
3954         CGparameter vp_ShadowMapMatrix;
3955
3956         CGparameter fp_Texture_First;
3957         CGparameter fp_Texture_Second;
3958         CGparameter fp_Texture_GammaRamps;
3959         CGparameter fp_Texture_Normal;
3960         CGparameter fp_Texture_Color;
3961         CGparameter fp_Texture_Gloss;
3962         CGparameter fp_Texture_Glow;
3963         CGparameter fp_Texture_SecondaryNormal;
3964         CGparameter fp_Texture_SecondaryColor;
3965         CGparameter fp_Texture_SecondaryGloss;
3966         CGparameter fp_Texture_SecondaryGlow;
3967         CGparameter fp_Texture_Pants;
3968         CGparameter fp_Texture_Shirt;
3969         CGparameter fp_Texture_FogHeightTexture;
3970         CGparameter fp_Texture_FogMask;
3971         CGparameter fp_Texture_Lightmap;
3972         CGparameter fp_Texture_Deluxemap;
3973         CGparameter fp_Texture_Attenuation;
3974         CGparameter fp_Texture_Cube;
3975         CGparameter fp_Texture_Refraction;
3976         CGparameter fp_Texture_Reflection;
3977         CGparameter fp_Texture_ShadowMapRect;
3978         CGparameter fp_Texture_ShadowMapCube;
3979         CGparameter fp_Texture_ShadowMap2D;
3980         CGparameter fp_Texture_CubeProjection;
3981         CGparameter fp_Texture_ScreenDepth;
3982         CGparameter fp_Texture_ScreenNormalMap;
3983         CGparameter fp_Texture_ScreenDiffuse;
3984         CGparameter fp_Texture_ScreenSpecular;
3985         CGparameter fp_Texture_ReflectMask;
3986         CGparameter fp_Texture_ReflectCube;
3987         CGparameter fp_Alpha;
3988         CGparameter fp_BloomBlur_Parameters;
3989         CGparameter fp_ClientTime;
3990         CGparameter fp_Color_Ambient;
3991         CGparameter fp_Color_Diffuse;
3992         CGparameter fp_Color_Specular;
3993         CGparameter fp_Color_Glow;
3994         CGparameter fp_Color_Pants;
3995         CGparameter fp_Color_Shirt;
3996         CGparameter fp_DeferredColor_Ambient;
3997         CGparameter fp_DeferredColor_Diffuse;
3998         CGparameter fp_DeferredColor_Specular;
3999         CGparameter fp_DeferredMod_Diffuse;
4000         CGparameter fp_DeferredMod_Specular;
4001         CGparameter fp_DistortScaleRefractReflect;
4002         CGparameter fp_EyePosition;
4003         CGparameter fp_FogColor;
4004         CGparameter fp_FogHeightFade;
4005         CGparameter fp_FogPlane;
4006         CGparameter fp_FogPlaneViewDist;
4007         CGparameter fp_FogRangeRecip;
4008         CGparameter fp_LightColor;
4009         CGparameter fp_LightDir;
4010         CGparameter fp_LightPosition;
4011         CGparameter fp_OffsetMapping_Scale;
4012         CGparameter fp_PixelSize;
4013         CGparameter fp_ReflectColor;
4014         CGparameter fp_ReflectFactor;
4015         CGparameter fp_ReflectOffset;
4016         CGparameter fp_RefractColor;
4017         CGparameter fp_Saturation;
4018         CGparameter fp_ScreenCenterRefractReflect;
4019         CGparameter fp_ScreenScaleRefractReflect;
4020         CGparameter fp_ScreenToDepth;
4021         CGparameter fp_ShadowMap_Parameters;
4022         CGparameter fp_ShadowMap_TextureScale;
4023         CGparameter fp_SpecularPower;
4024         CGparameter fp_UserVec1;
4025         CGparameter fp_UserVec2;
4026         CGparameter fp_UserVec3;
4027         CGparameter fp_UserVec4;
4028         CGparameter fp_ViewTintColor;
4029         CGparameter fp_ViewToLight;
4030         CGparameter fp_PixelToScreenTexCoord;
4031         CGparameter fp_ModelToReflectCube;
4032         CGparameter fp_NormalmapScrollBlend;
4033 }
4034 r_cg_permutation_t;
4035
4036 /// information about each possible shader permutation
4037 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4038 /// currently selected permutation
4039 r_cg_permutation_t *r_cg_permutation;
4040 /// storage for permutations linked in the hash table
4041 memexpandablearray_t r_cg_permutationarray;
4042
4043 #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));}}
4044
4045 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4046 {
4047         //unsigned int hashdepth = 0;
4048         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4049         r_cg_permutation_t *p;
4050         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4051         {
4052                 if (p->mode == mode && p->permutation == permutation)
4053                 {
4054                         //if (hashdepth > 10)
4055                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4056                         return p;
4057                 }
4058                 //hashdepth++;
4059         }
4060         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4061         p->mode = mode;
4062         p->permutation = permutation;
4063         p->hashnext = r_cg_permutationhash[mode][hashindex];
4064         r_cg_permutationhash[mode][hashindex] = p;
4065         //if (hashdepth > 10)
4066         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4067         return p;
4068 }
4069
4070 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4071 {
4072         char *shaderstring;
4073         if (!filename || !filename[0])
4074                 return NULL;
4075         if (!strcmp(filename, "cg/default.cg"))
4076         {
4077                 if (!cgshaderstring)
4078                 {
4079                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4080                         if (cgshaderstring)
4081                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4082                         else
4083                                 cgshaderstring = (char *)builtincgshaderstring;
4084                 }
4085                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4086                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4087                 return shaderstring;
4088         }
4089         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4090         if (shaderstring)
4091         {
4092                 if (printfromdisknotice)
4093                         Con_DPrintf("from disk %s... ", filename);
4094                 return shaderstring;
4095         }
4096         return shaderstring;
4097 }
4098
4099 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4100 {
4101         // TODO: load or create .fp and .vp shader files
4102 }
4103
4104 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4105 {
4106         int i;
4107         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4108         int vertstrings_count = 0, vertstring_length = 0;
4109         int geomstrings_count = 0, geomstring_length = 0;
4110         int fragstrings_count = 0, fragstring_length = 0;
4111         char *vertexstring, *geometrystring, *fragmentstring;
4112         const char *vertstrings_list[32+3];
4113         const char *geomstrings_list[32+3];
4114         const char *fragstrings_list[32+3];
4115         char *vertstring, *geomstring, *fragstring;
4116         char permutationname[256];
4117         char cachename[256];
4118         CGprofile vertexProfile;
4119         CGprofile fragmentProfile;
4120
4121         if (p->compiled)
4122                 return;
4123         p->compiled = true;
4124         p->vprogram = NULL;
4125         p->fprogram = NULL;
4126
4127         permutationname[0] = 0;
4128         cachename[0] = 0;
4129         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4130         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4131         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4132
4133         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4134         strlcat(cachename, "cg/", sizeof(cachename));
4135
4136         // the first pretext is which type of shader to compile as
4137         // (later these will all be bound together as a program object)
4138         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4139         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4140         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4141
4142         // the second pretext is the mode (for example a light source)
4143         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4144         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4145         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4146         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4147         strlcat(cachename, modeinfo->name, sizeof(cachename));
4148
4149         // now add all the permutation pretexts
4150         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4151         {
4152                 if (permutation & (1<<i))
4153                 {
4154                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4155                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4156                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4157                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4158                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4159                 }
4160                 else
4161                 {
4162                         // keep line numbers correct
4163                         vertstrings_list[vertstrings_count++] = "\n";
4164                         geomstrings_list[geomstrings_count++] = "\n";
4165                         fragstrings_list[fragstrings_count++] = "\n";
4166                 }
4167         }
4168
4169         // add static parms
4170         R_CompileShader_AddStaticParms(mode, permutation);
4171
4172         // replace spaces in the cachename with _ characters
4173         for (i = 0;cachename[i];i++)
4174                 if (cachename[i] == ' ')
4175                         cachename[i] = '_';
4176
4177         // now append the shader text itself
4178         vertstrings_list[vertstrings_count++] = vertexstring;
4179         geomstrings_list[geomstrings_count++] = geometrystring;
4180         fragstrings_list[fragstrings_count++] = fragmentstring;
4181
4182         // if any sources were NULL, clear the respective list
4183         if (!vertexstring)
4184                 vertstrings_count = 0;
4185         if (!geometrystring)
4186                 geomstrings_count = 0;
4187         if (!fragmentstring)
4188                 fragstrings_count = 0;
4189
4190         vertstring_length = 0;
4191         for (i = 0;i < vertstrings_count;i++)
4192                 vertstring_length += strlen(vertstrings_list[i]);
4193         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4194         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4195                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4196
4197         geomstring_length = 0;
4198         for (i = 0;i < geomstrings_count;i++)
4199                 geomstring_length += strlen(geomstrings_list[i]);
4200         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4201         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4202                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4203
4204         fragstring_length = 0;
4205         for (i = 0;i < fragstrings_count;i++)
4206                 fragstring_length += strlen(fragstrings_list[i]);
4207         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4208         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4209                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4210
4211         CHECKGLERROR
4212         CHECKCGERROR
4213         //vertexProfile = CG_PROFILE_ARBVP1;
4214         //fragmentProfile = CG_PROFILE_ARBFP1;
4215         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4216         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4217         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4218         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4219         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4220         CHECKGLERROR
4221
4222         // try to load the cached shader, or generate one
4223         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4224
4225         // if caching failed, do a dynamic compile for now
4226         CHECKCGERROR
4227         if (vertstring[0] && !p->vprogram)
4228                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4229         CHECKCGERROR
4230         if (fragstring[0] && !p->fprogram)
4231                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4232         CHECKCGERROR
4233
4234         // look up all the uniform variable names we care about, so we don't
4235         // have to look them up every time we set them
4236         if (p->vprogram)
4237         {
4238                 CHECKCGERROR
4239                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4240                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4241                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4242                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4243                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4244                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4245                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4246                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4247                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4248                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4249                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4250                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4251                 CHECKCGERROR
4252         }
4253         if (p->fprogram)
4254         {
4255                 CHECKCGERROR
4256                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4257                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4258                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4259                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4260                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4261                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4262                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4263                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4264                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4265                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4266                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4267                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4268                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4269                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4270                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4271                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4272                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4273                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4274                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4275                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4276                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4277                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4278                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4279                 p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4280                 p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4281                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4282                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4283                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4284                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4285                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4286                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4287                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4288                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4289                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4290                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4291                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4292                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4293                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4294                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4295                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4296                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4297                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4298                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4299                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4300                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4301                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4302                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4303                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4304                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4305                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4306                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4307                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4308                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4309                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4310                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4311                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4312                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4313                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4314                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4315                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4316                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4317                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4318                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4319                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4320                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4321                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4322                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4323                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4324                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4325                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4326                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4327                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4328                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4329                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4330                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4331                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4332                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4333                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4334                 p->fp_NormalmapScrollBlend       = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4335                 CHECKCGERROR
4336         }
4337
4338         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4339                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4340         else
4341                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4342
4343         // free the strings
4344         if (vertstring)
4345                 Mem_Free(vertstring);
4346         if (geomstring)
4347                 Mem_Free(geomstring);
4348         if (fragstring)
4349                 Mem_Free(fragstring);
4350         if (vertexstring)
4351                 Mem_Free(vertexstring);
4352         if (geometrystring)
4353                 Mem_Free(geometrystring);
4354         if (fragmentstring)
4355                 Mem_Free(fragmentstring);
4356 }
4357
4358 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4359 {
4360         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4361         CHECKGLERROR
4362         CHECKCGERROR
4363         if (r_cg_permutation != perm)
4364         {
4365                 r_cg_permutation = perm;
4366                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4367                 {
4368                         if (!r_cg_permutation->compiled)
4369                                 R_CG_CompilePermutation(perm, mode, permutation);
4370                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4371                         {
4372                                 // remove features until we find a valid permutation
4373                                 int i;
4374                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4375                                 {
4376                                         // reduce i more quickly whenever it would not remove any bits
4377                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4378                                         if (!(permutation & j))
4379                                                 continue;
4380                                         permutation -= j;
4381                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4382                                         if (!r_cg_permutation->compiled)
4383                                                 R_CG_CompilePermutation(perm, mode, permutation);
4384                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4385                                                 break;
4386                                 }
4387                                 if (i >= SHADERPERMUTATION_COUNT)
4388                                 {
4389                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4390                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4391                                         return; // no bit left to clear, entire mode is broken
4392                                 }
4393                         }
4394                 }
4395                 CHECKGLERROR
4396                 CHECKCGERROR
4397                 if (r_cg_permutation->vprogram)
4398                 {
4399                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4400                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4401                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4402                 }
4403                 else
4404                 {
4405                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4406                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4407                 }
4408                 if (r_cg_permutation->fprogram)
4409                 {
4410                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4411                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4412                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4413                 }
4414                 else
4415                 {
4416                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4417                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4418                 }
4419         }
4420         CHECKCGERROR
4421         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4422         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4423         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4424 }
4425
4426 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4427 {
4428         cgGLSetTextureParameter(param, R_GetTexture(tex));
4429         cgGLEnableTextureParameter(param);
4430 }
4431 #endif
4432
4433 void R_GLSL_Restart_f(void)
4434 {
4435         unsigned int i, limit;
4436         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4437                 Mem_Free(glslshaderstring);
4438         glslshaderstring = NULL;
4439         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4440                 Mem_Free(cgshaderstring);
4441         cgshaderstring = NULL;
4442         switch(vid.renderpath)
4443         {
4444         case RENDERPATH_GL20:
4445                 {
4446                         r_glsl_permutation_t *p;
4447                         r_glsl_permutation = NULL;
4448                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4449                         for (i = 0;i < limit;i++)
4450                         {
4451                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4452                                 {
4453                                         GL_Backend_FreeProgram(p->program);
4454                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4455                                 }
4456                         }
4457                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4458                 }
4459                 break;
4460         case RENDERPATH_CGGL:
4461 #ifdef SUPPORTCG
4462                 {
4463                         r_cg_permutation_t *p;
4464                         r_cg_permutation = NULL;
4465                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4466                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4467                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4468                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4469                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4470                         for (i = 0;i < limit;i++)
4471                         {
4472                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4473                                 {
4474                                         if (p->vprogram)
4475                                                 cgDestroyProgram(p->vprogram);
4476                                         if (p->fprogram)
4477                                                 cgDestroyProgram(p->fprogram);
4478                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4479                                 }
4480                         }
4481                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4482                 }
4483                 break;
4484 #endif
4485         case RENDERPATH_GL13:
4486         case RENDERPATH_GL11:
4487                 break;
4488         }
4489 }
4490
4491 void R_GLSL_DumpShader_f(void)
4492 {
4493         int i;
4494         qfile_t *file;
4495
4496         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4497         if (file)
4498         {
4499                 FS_Print(file, "/* The engine may define the following macros:\n");
4500                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4501                 for (i = 0;i < SHADERMODE_COUNT;i++)
4502                         FS_Print(file, glslshadermodeinfo[i].pretext);
4503                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4504                         FS_Print(file, shaderpermutationinfo[i].pretext);
4505                 FS_Print(file, "*/\n");
4506                 FS_Print(file, builtinshaderstring);
4507                 FS_Close(file);
4508                 Con_Printf("glsl/default.glsl written\n");
4509         }
4510         else
4511                 Con_Printf("failed to write to glsl/default.glsl\n");
4512
4513 #ifdef SUPPORTCG
4514         file = FS_OpenRealFile("cg/default.cg", "w", false);
4515         if (file)
4516         {
4517                 FS_Print(file, "/* The engine may define the following macros:\n");
4518                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4519                 for (i = 0;i < SHADERMODE_COUNT;i++)
4520                         FS_Print(file, cgshadermodeinfo[i].pretext);
4521                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4522                         FS_Print(file, shaderpermutationinfo[i].pretext);
4523                 FS_Print(file, "*/\n");
4524                 FS_Print(file, builtincgshaderstring);
4525                 FS_Close(file);
4526                 Con_Printf("cg/default.cg written\n");
4527         }
4528         else
4529                 Con_Printf("failed to write to cg/default.cg\n");
4530 #endif
4531 }
4532
4533 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4534 {
4535         if (!second)
4536                 texturemode = GL_MODULATE;
4537         switch (vid.renderpath)
4538         {
4539         case RENDERPATH_GL20:
4540                 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))));
4541                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4542                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4543                 break;
4544         case RENDERPATH_CGGL:
4545 #ifdef SUPPORTCG
4546                 CHECKCGERROR
4547                 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))));
4548                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4549                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4550 #endif
4551                 break;
4552         case RENDERPATH_GL13:
4553                 R_Mesh_TexBind(0, first );
4554                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4555                 R_Mesh_TexBind(1, second);
4556                 if (second)
4557                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4558                 break;
4559         case RENDERPATH_GL11:
4560                 R_Mesh_TexBind(0, first );
4561                 break;
4562         }
4563 }
4564
4565 void R_SetupShader_DepthOrShadow(void)
4566 {
4567         switch (vid.renderpath)
4568         {
4569         case RENDERPATH_GL20:
4570                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4571                 break;
4572         case RENDERPATH_CGGL:
4573 #ifdef SUPPORTCG
4574                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4575 #endif
4576                 break;
4577         case RENDERPATH_GL13:
4578                 R_Mesh_TexBind(0, 0);
4579                 R_Mesh_TexBind(1, 0);
4580                 break;
4581         case RENDERPATH_GL11:
4582                 R_Mesh_TexBind(0, 0);
4583                 break;
4584         }
4585 }
4586
4587 void R_SetupShader_ShowDepth(void)
4588 {
4589         switch (vid.renderpath)
4590         {
4591         case RENDERPATH_GL20:
4592                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4593                 break;
4594         case RENDERPATH_CGGL:
4595 #ifdef SUPPORTCG
4596                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4597 #endif
4598                 break;
4599         case RENDERPATH_GL13:
4600                 break;
4601         case RENDERPATH_GL11:
4602                 break;
4603         }
4604 }
4605
4606 extern qboolean r_shadow_usingdeferredprepass;
4607 extern cvar_t r_shadow_deferred_8bitrange;
4608 extern rtexture_t *r_shadow_attenuationgradienttexture;
4609 extern rtexture_t *r_shadow_attenuation2dtexture;
4610 extern rtexture_t *r_shadow_attenuation3dtexture;
4611 extern qboolean r_shadow_usingshadowmaprect;
4612 extern qboolean r_shadow_usingshadowmapcube;
4613 extern qboolean r_shadow_usingshadowmap2d;
4614 extern qboolean r_shadow_usingshadowmaportho;
4615 extern float r_shadow_shadowmap_texturescale[2];
4616 extern float r_shadow_shadowmap_parameters[4];
4617 extern qboolean r_shadow_shadowmapvsdct;
4618 extern qboolean r_shadow_shadowmapsampler;
4619 extern int r_shadow_shadowmappcf;
4620 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4621 extern rtexture_t *r_shadow_shadowmap2dtexture;
4622 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4623 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4624 extern matrix4x4_t r_shadow_shadowmapmatrix;
4625 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4626 extern int r_shadow_prepass_width;
4627 extern int r_shadow_prepass_height;
4628 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4629 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4630 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4631 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4632 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
4633 {
4634         // a blendfunc allows colormod if:
4635         // a) it can never keep the destination pixel invariant, or
4636         // b) it can keep the destination pixel invariant, and still can do so if colormodded
4637         // this is to prevent unintended side effects from colormod
4638
4639         // in formulas:
4640         // IF there is a (s, sa) for which for all (d, da),
4641         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4642         // THEN, for this (s, sa) and all (colormod, d, da):
4643         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
4644         // OBVIOUSLY, this means that
4645         //   s*colormod * src(s*colormod, d, sa, da) = 0
4646         //   dst(s*colormod, d, sa, da)              = 1
4647
4648         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
4649
4650         // main condition to leave dst color invariant:
4651         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4652         //   src == GL_ZERO:
4653         //     s * 0 + d * dst(s, d, sa, da) == d
4654         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4655         //       => colormod is a problem for GL_SRC_COLOR only
4656         //   src == GL_ONE:
4657         //     s + d * dst(s, d, sa, da) == d
4658         //       => s == 0
4659         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4660         //       => colormod is never problematic for these
4661         //   src == GL_SRC_COLOR:
4662         //     s*s + d * dst(s, d, sa, da) == d
4663         //       => s == 0
4664         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4665         //       => colormod is never problematic for these
4666         //   src == GL_ONE_MINUS_SRC_COLOR:
4667         //     s*(1-s) + d * dst(s, d, sa, da) == d
4668         //       => s == 0 or s == 1
4669         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4670         //       => colormod is a problem for GL_SRC_COLOR only
4671         //   src == GL_DST_COLOR
4672         //     s*d + d * dst(s, d, sa, da) == d
4673         //       => s == 1
4674         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4675         //       => colormod is always a problem
4676         //     or
4677         //       => s == 0
4678         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4679         //       => colormod is never problematic for these
4680         //       => BUT, we do not know s! We must assume it is problematic
4681         //       then... except in GL_ONE case, where we know all invariant
4682         //       cases are fine
4683         //   src == GL_ONE_MINUS_DST_COLOR
4684         //     s*(1-d) + d * dst(s, d, sa, da) == d
4685         //       => s == 0 (1-d is impossible to handle for our desired result)
4686         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4687         //       => colormod is never problematic for these
4688         //   src == GL_SRC_ALPHA
4689         //     s*sa + d * dst(s, d, sa, da) == d
4690         //       => s == 0, or sa == 0
4691         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4692         //       => colormod breaks in the case GL_SRC_COLOR only
4693         //   src == GL_ONE_MINUS_SRC_ALPHA
4694         //     s*(1-sa) + d * dst(s, d, sa, da) == d
4695         //       => s == 0, or sa == 1
4696         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4697         //       => colormod breaks in the case GL_SRC_COLOR only
4698         //   src == GL_DST_ALPHA
4699         //     s*da + d * dst(s, d, sa, da) == d
4700         //       => s == 0
4701         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4702         //       => colormod is never problematic for these
4703
4704         switch(src)
4705         {
4706                 case GL_ZERO:
4707                 case GL_ONE_MINUS_SRC_COLOR:
4708                 case GL_SRC_ALPHA:
4709                 case GL_ONE_MINUS_SRC_ALPHA:
4710                         if(dst == GL_SRC_COLOR)
4711                                 return false;
4712                         return true;
4713                 case GL_ONE:
4714                 case GL_SRC_COLOR:
4715                 case GL_ONE_MINUS_DST_COLOR:
4716                 case GL_DST_ALPHA:
4717                 case GL_ONE_MINUS_DST_ALPHA:
4718                         return true;
4719                 case GL_DST_COLOR:
4720                         if(dst == GL_ONE)
4721                                 return true;
4722                         return false;
4723                 default:
4724                         return false;
4725         }
4726 }
4727 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4728 {
4729         // select a permutation of the lighting shader appropriate to this
4730         // combination of texture, entity, light source, and fogging, only use the
4731         // minimum features necessary to avoid wasting rendering time in the
4732         // fragment shader on features that are not being used
4733         unsigned int permutation = 0;
4734         unsigned int mode = 0;
4735         qboolean allow_colormod;
4736         static float dummy_colormod[3] = {1, 1, 1};
4737         float *colormod = rsurface.colormod;
4738         float m16f[16];
4739         if (rsurfacepass == RSURFPASS_BACKGROUND)
4740         {
4741                 // distorted background
4742                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4743                 {
4744                         mode = SHADERMODE_WATER;
4745                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
4746                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
4747                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4748                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4749                 }
4750                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
4751                 {
4752                         mode = SHADERMODE_REFRACTION;
4753                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4754                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4755                 }
4756                 else
4757                 {
4758                         mode = SHADERMODE_GENERIC;
4759                         permutation |= SHADERPERMUTATION_DIFFUSE;
4760                         GL_BlendFunc(GL_ONE, GL_ZERO);
4761                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4762                 }
4763                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4764                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4765                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4766                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4767                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4768                 R_Mesh_ColorPointer(NULL, 0, 0);
4769                 GL_AlphaTest(false);
4770         }
4771         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4772         {
4773                 if (r_glsl_offsetmapping.integer)
4774                 {
4775                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4776                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4777                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4778                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4779                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4780                         {
4781                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4782                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4783                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4784                         }
4785                 }
4786                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4787                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4788                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4789                         permutation |= SHADERPERMUTATION_ALPHAKILL;
4790                 // normalmap (deferred prepass), may use alpha test on diffuse
4791                 mode = SHADERMODE_DEFERREDGEOMETRY;
4792                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4793                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4794                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4795                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4796                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4797                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4798                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4799                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4800                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4801                 else
4802                         R_Mesh_ColorPointer(NULL, 0, 0);
4803                 GL_AlphaTest(false);
4804                 GL_BlendFunc(GL_ONE, GL_ZERO);
4805                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4806         }
4807         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4808         {
4809                 if (r_glsl_offsetmapping.integer)
4810                 {
4811                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4812                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4813                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4814                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4815                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4816                         {
4817                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4818                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4819                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4820                         }
4821                 }
4822                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4823                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4824                 // light source
4825                 mode = SHADERMODE_LIGHTSOURCE;
4826                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4827                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4828                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4829                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4830                 if (diffusescale > 0)
4831                         permutation |= SHADERPERMUTATION_DIFFUSE;
4832                 if (specularscale > 0)
4833                 {
4834                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4835                         if (r_shadow_glossexact.integer)
4836                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4837                 }
4838                 if (r_refdef.fogenabled)
4839                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4840                 if (rsurface.texture->colormapping)
4841                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4842                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4843                 {
4844                         if (r_shadow_usingshadowmaprect)
4845                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4846                         if (r_shadow_usingshadowmap2d)
4847                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4848                         if (r_shadow_usingshadowmapcube)
4849                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4850                         else if(r_shadow_shadowmapvsdct)
4851                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4852
4853                         if (r_shadow_shadowmapsampler)
4854                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4855                         if (r_shadow_shadowmappcf > 1)
4856                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4857                         else if (r_shadow_shadowmappcf)
4858                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4859                 }
4860                 if (rsurface.texture->reflectmasktexture)
4861                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4862                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4863                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4864                 {
4865                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4866                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4867                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4868                 }
4869                 else
4870                 {
4871                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4872                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4873                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4874                 }
4875                 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4876                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4877                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4878                 else
4879                         R_Mesh_ColorPointer(NULL, 0, 0);
4880                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4881                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4882                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
4883         }
4884         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4885         {
4886                 if (r_glsl_offsetmapping.integer)
4887                 {
4888                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4889                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4890                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4891                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4892                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4893                         {
4894                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4895                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4896                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4897                         }
4898                 }
4899                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4900                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4901                 // unshaded geometry (fullbright or ambient model lighting)
4902                 mode = SHADERMODE_FLATCOLOR;
4903                 ambientscale = diffusescale = specularscale = 0;
4904                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4905                         permutation |= SHADERPERMUTATION_GLOW;
4906                 if (r_refdef.fogenabled)
4907                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4908                 if (rsurface.texture->colormapping)
4909                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4910                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4911                 {
4912                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4913                         if (r_shadow_usingshadowmaprect)
4914                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4915                         if (r_shadow_usingshadowmap2d)
4916                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4917
4918                         if (r_shadow_shadowmapsampler)
4919                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4920                         if (r_shadow_shadowmappcf > 1)
4921                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4922                         else if (r_shadow_shadowmappcf)
4923                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4924                 }
4925                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4926                         permutation |= SHADERPERMUTATION_REFLECTION;
4927                 if (rsurface.texture->reflectmasktexture)
4928                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4929                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4930                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4931                 {
4932                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4933                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4934                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4935                 }
4936                 else
4937                 {
4938                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4939                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4940                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4941                 }
4942                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4943                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4944                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4945                 else
4946                         R_Mesh_ColorPointer(NULL, 0, 0);
4947                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4948                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4949                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4950         }
4951         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4952         {
4953                 if (r_glsl_offsetmapping.integer)
4954                 {
4955                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4956                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4957                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4958                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4959                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4960                         {
4961                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4962                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4963                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4964                         }
4965                 }
4966                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4967                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4968                 // directional model lighting
4969                 mode = SHADERMODE_LIGHTDIRECTION;
4970                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4971                         permutation |= SHADERPERMUTATION_GLOW;
4972                 permutation |= SHADERPERMUTATION_DIFFUSE;
4973                 if (specularscale > 0)
4974                 {
4975                         permutation |= SHADERPERMUTATION_SPECULAR;
4976                         if (r_shadow_glossexact.integer)
4977                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4978                 }
4979                 if (r_refdef.fogenabled)
4980                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4981                 if (rsurface.texture->colormapping)
4982                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4983                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4984                 {
4985                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4986                         if (r_shadow_usingshadowmaprect)
4987                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4988                         if (r_shadow_usingshadowmap2d)
4989                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4990
4991                         if (r_shadow_shadowmapsampler)
4992                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4993                         if (r_shadow_shadowmappcf > 1)
4994                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4995                         else if (r_shadow_shadowmappcf)
4996                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4997                 }
4998                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4999                         permutation |= SHADERPERMUTATION_REFLECTION;
5000                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5001                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5002                 if (rsurface.texture->reflectmasktexture)
5003                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5004                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5005                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
5006                 {
5007                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5008                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5009                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5010                 }
5011                 else
5012                 {
5013                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
5014                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
5015                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
5016                 }
5017                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
5018                 R_Mesh_ColorPointer(NULL, 0, 0);
5019                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5020                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5021                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5022         }
5023         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5024         {
5025                 if (r_glsl_offsetmapping.integer)
5026                 {
5027                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5028                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5029                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5030                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5031                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5032                         {
5033                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5034                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5035                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5036                         }
5037                 }
5038                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5039                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5040                 // ambient model lighting
5041                 mode = SHADERMODE_LIGHTDIRECTION;
5042                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5043                         permutation |= SHADERPERMUTATION_GLOW;
5044                 if (r_refdef.fogenabled)
5045                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5046                 if (rsurface.texture->colormapping)
5047                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5048                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5049                 {
5050                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5051                         if (r_shadow_usingshadowmaprect)
5052                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5053                         if (r_shadow_usingshadowmap2d)
5054                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5055
5056                         if (r_shadow_shadowmapsampler)
5057                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5058                         if (r_shadow_shadowmappcf > 1)
5059                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5060                         else if (r_shadow_shadowmappcf)
5061                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5062                 }
5063                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5064                         permutation |= SHADERPERMUTATION_REFLECTION;
5065                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5066                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5067                 if (rsurface.texture->reflectmasktexture)
5068                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5069                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5070                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
5071                 {
5072                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5073                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5074                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5075                 }
5076                 else
5077                 {
5078                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
5079                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
5080                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
5081                 }
5082                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
5083                 R_Mesh_ColorPointer(NULL, 0, 0);
5084                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5085                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5086                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5087         }
5088         else
5089         {
5090                 if (r_glsl_offsetmapping.integer)
5091                 {
5092                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5093                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5094                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5095                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5096                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5097                         {
5098                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5099                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5100                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5101                         }
5102                 }
5103                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5104                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5105                 // lightmapped wall
5106                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5107                         permutation |= SHADERPERMUTATION_GLOW;
5108                 if (r_refdef.fogenabled)
5109                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5110                 if (rsurface.texture->colormapping)
5111                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5112                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5113                 {
5114                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5115                         if (r_shadow_usingshadowmaprect)
5116                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5117                         if (r_shadow_usingshadowmap2d)
5118                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5119
5120                         if (r_shadow_shadowmapsampler)
5121                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5122                         if (r_shadow_shadowmappcf > 1)
5123                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5124                         else if (r_shadow_shadowmappcf)
5125                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5126                 }
5127                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5128                         permutation |= SHADERPERMUTATION_REFLECTION;
5129                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5130                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5131                 if (rsurface.texture->reflectmasktexture)
5132                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5133                 if (FAKELIGHT_ENABLED)
5134                 {
5135                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5136                         mode = SHADERMODE_FAKELIGHT;
5137                         permutation |= SHADERPERMUTATION_DIFFUSE;
5138                         if (specularscale > 0)
5139                         {
5140                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5141                                 if (r_shadow_glossexact.integer)
5142                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5143                         }
5144                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
5145                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5146                         else
5147                                 R_Mesh_ColorPointer(NULL, 0, 0);
5148                 }
5149                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5150                 {
5151                         // deluxemapping (light direction texture)
5152                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5153                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5154                         else
5155                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5156                         permutation |= SHADERPERMUTATION_DIFFUSE;
5157                         if (specularscale > 0)
5158                         {
5159                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5160                                 if (r_shadow_glossexact.integer)
5161                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5162                         }
5163                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5164                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
5165                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5166                         else
5167                                 R_Mesh_ColorPointer(NULL, 0, 0);
5168                 }
5169                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5170                 {
5171                         // fake deluxemapping (uniform light direction in tangentspace)
5172                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5173                         permutation |= SHADERPERMUTATION_DIFFUSE;
5174                         if (specularscale > 0)
5175                         {
5176                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5177                                 if (r_shadow_glossexact.integer)
5178                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5179                         }
5180                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5181                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
5182                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5183                         else
5184                                 R_Mesh_ColorPointer(NULL, 0, 0);
5185                 }
5186                 else if (rsurface.uselightmaptexture)
5187                 {
5188                         // ordinary lightmapping (q1bsp, q3bsp)
5189                         mode = SHADERMODE_LIGHTMAP;
5190                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5191                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
5192                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5193                         else
5194                                 R_Mesh_ColorPointer(NULL, 0, 0);
5195                 }
5196                 else
5197                 {
5198                         // ordinary vertex coloring (q3bsp)
5199                         mode = SHADERMODE_VERTEXCOLOR;
5200                         R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
5201                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5202                 }
5203                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5204                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
5205                 {
5206                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5207                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5208                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5209                 }
5210                 else
5211                 {
5212                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
5213                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
5214                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
5215                 }
5216                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5217                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5218                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5219         }
5220         if(!allow_colormod)
5221                 colormod = dummy_colormod;
5222         switch(vid.renderpath)
5223         {
5224         case RENDERPATH_GL20:
5225                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5226                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5227                 if (mode == SHADERMODE_LIGHTSOURCE)
5228                 {
5229                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5230                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5231                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5232                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5233                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5234                         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);
5235         
5236                         // additive passes are only darkened by fog, not tinted
5237                         if (r_glsl_permutation->loc_FogColor >= 0)
5238                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5239                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5240                 }
5241                 else
5242                 {
5243                         if (mode == SHADERMODE_FLATCOLOR)
5244                         {
5245                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5246                         }
5247                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5248                         {
5249                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
5250                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5251                                 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);
5252                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5253                                 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);
5254                                 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]);
5255                                 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]);
5256                         }
5257                         else
5258                         {
5259                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5260                                 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]);
5261                                 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);
5262                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5263                                 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);
5264                         }
5265                         // additive passes are only darkened by fog, not tinted
5266                         if (r_glsl_permutation->loc_FogColor >= 0)
5267                         {
5268                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5269                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5270                                 else
5271                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5272                         }
5273                         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);
5274                         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]);
5275                         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]);
5276                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5277                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5278                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5279                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5280                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5281                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2fARB(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5282                 }
5283                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5284                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5285                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5286                 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]);
5287                 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]);
5288
5289                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5290                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
5291                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5292                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5293                 {
5294                         if (rsurface.texture->pantstexture)
5295                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5296                         else
5297                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5298                 }
5299                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5300                 {
5301                         if (rsurface.texture->shirttexture)
5302                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5303                         else
5304                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5305                 }
5306                 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]);
5307                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5308                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5309                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5310                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5311                 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]);
5312                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5313
5314         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5315         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5316         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5317                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5318                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5319                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5320                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5321                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5322                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5323                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5324                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5325                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5326                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5327                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5328                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5329                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5330                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5331                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
5332                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , r_texture_blanknormalmap                            );
5333                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5334                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
5335                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
5336                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5337                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5338                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5339                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5340                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5341                 {
5342                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5343                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture                  );
5344                         if (rsurface.rtlight)
5345                         {
5346                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5347                                 if (r_shadow_usingshadowmapcube)
5348                                         if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5349                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5350                         }
5351                 }
5352                 CHECKGLERROR
5353                 break;
5354         case RENDERPATH_CGGL:
5355 #ifdef SUPPORTCG
5356                 R_SetupShader_SetPermutationCG(mode, permutation);
5357                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5358                 if (mode == SHADERMODE_LIGHTSOURCE)
5359                 {
5360                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5361                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5362                 }
5363                 else
5364                 {
5365                         if (mode == SHADERMODE_LIGHTDIRECTION)
5366                         {
5367                                 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
5368                         }
5369                 }
5370                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5371                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5372                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5373                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5374                 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
5375                 CHECKGLERROR
5376
5377                 if (mode == SHADERMODE_LIGHTSOURCE)
5378                 {
5379                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5380                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5381                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
5382                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
5383                         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
5384
5385                         // additive passes are only darkened by fog, not tinted
5386                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5387                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5388                 }
5389                 else
5390                 {
5391                         if (mode == SHADERMODE_FLATCOLOR)
5392                         {
5393                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
5394                         }
5395                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5396                         {
5397                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);CHECKCGERROR
5398                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);CHECKCGERROR
5399                                 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
5400                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);CHECKCGERROR
5401                                 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
5402                                 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
5403                                 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
5404                         }
5405                         else
5406                         {
5407                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);CHECKCGERROR
5408                                 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
5409                                 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
5410                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
5411                                 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
5412                         }
5413                         // additive passes are only darkened by fog, not tinted
5414                         if (r_cg_permutation->fp_FogColor)
5415                         {
5416                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5417                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5418                                 else
5419                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5420                                 CHECKCGERROR
5421                         }
5422                         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
5423                         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
5424                         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
5425                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5426                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5427                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5428                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5429                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5430                         if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5431                 }
5432                 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
5433                 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
5434                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5435                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));CHECKCGERROR
5436                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5437                 if (r_cg_permutation->fp_Color_Pants)
5438                 {
5439                         if (rsurface.texture->pantstexture)
5440                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5441                         else
5442                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5443                         CHECKCGERROR
5444                 }
5445                 if (r_cg_permutation->fp_Color_Shirt)
5446                 {
5447                         if (rsurface.texture->shirttexture)
5448                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5449                         else
5450                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5451                         CHECKCGERROR
5452                 }
5453                 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
5454                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5455                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5456                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5457                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5458                 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
5459                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5460
5461         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
5462         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
5463         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
5464                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
5465                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
5466                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
5467                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
5468                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
5469                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
5470                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
5471                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
5472                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
5473                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
5474                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
5475                 if (r_cg_permutation->fp_Texture_ReflectCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectCube    , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);CHECKCGERROR
5476                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
5477                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
5478                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
5479                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
5480                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5481                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
5482                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
5483                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5484                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5485                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
5486                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
5487                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5488                 {
5489                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5490                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5491                         if (rsurface.rtlight)
5492                         {
5493                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5494                                 if (r_shadow_usingshadowmapcube)
5495                                         if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5496                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5497                         }
5498                 }
5499
5500                 CHECKGLERROR
5501 #endif
5502                 break;
5503         case RENDERPATH_GL13:
5504         case RENDERPATH_GL11:
5505                 break;
5506         }
5507 }
5508
5509 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5510 {
5511         // select a permutation of the lighting shader appropriate to this
5512         // combination of texture, entity, light source, and fogging, only use the
5513         // minimum features necessary to avoid wasting rendering time in the
5514         // fragment shader on features that are not being used
5515         unsigned int permutation = 0;
5516         unsigned int mode = 0;
5517         const float *lightcolorbase = rtlight->currentcolor;
5518         float ambientscale = rtlight->ambientscale;
5519         float diffusescale = rtlight->diffusescale;
5520         float specularscale = rtlight->specularscale;
5521         // this is the location of the light in view space
5522         vec3_t viewlightorigin;
5523         // this transforms from view space (camera) to light space (cubemap)
5524         matrix4x4_t viewtolight;
5525         matrix4x4_t lighttoview;
5526         float viewtolight16f[16];
5527         float range = 1.0f / r_shadow_deferred_8bitrange.value;
5528         // light source
5529         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5530         if (rtlight->currentcubemap != r_texture_whitecube)
5531                 permutation |= SHADERPERMUTATION_CUBEFILTER;
5532         if (diffusescale > 0)
5533                 permutation |= SHADERPERMUTATION_DIFFUSE;
5534         if (specularscale > 0)
5535         {
5536                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5537                 if (r_shadow_glossexact.integer)
5538                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5539         }
5540         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5541         {
5542                 if (r_shadow_usingshadowmaprect)
5543                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5544                 if (r_shadow_usingshadowmap2d)
5545                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5546                 if (r_shadow_usingshadowmapcube)
5547                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5548                 else if(r_shadow_shadowmapvsdct)
5549                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5550
5551                 if (r_shadow_shadowmapsampler)
5552                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5553                 if (r_shadow_shadowmappcf > 1)
5554                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5555                 else if (r_shadow_shadowmappcf)
5556                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5557         }
5558         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5559         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5560         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5561         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5562         switch(vid.renderpath)
5563         {
5564         case RENDERPATH_GL20:
5565                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5566                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5567                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
5568                 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);
5569                 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);
5570                 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);
5571                 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]);
5572                 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]);
5573                 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));
5574                 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]);
5575                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5576
5577                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5578                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5579                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5580                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5581                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
5582                 if (r_shadow_usingshadowmapcube)
5583                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5584                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
5585                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5586                 break;
5587         case RENDERPATH_CGGL:
5588 #ifdef SUPPORTCG
5589                 R_SetupShader_SetPermutationCG(mode, permutation);
5590                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5591                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5592                 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
5593                 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
5594                 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
5595                 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
5596                 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
5597                 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
5598                 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
5599                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5600
5601                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5602                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5603                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5604                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5605                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5606                 if (r_shadow_usingshadowmapcube)
5607                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5608                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5609                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5610 #endif
5611                 break;
5612         case RENDERPATH_GL13:
5613         case RENDERPATH_GL11:
5614                 break;
5615         }
5616 }
5617
5618 #define SKINFRAME_HASH 1024
5619
5620 typedef struct
5621 {
5622         int loadsequence; // incremented each level change
5623         memexpandablearray_t array;
5624         skinframe_t *hash[SKINFRAME_HASH];
5625 }
5626 r_skinframe_t;
5627 r_skinframe_t r_skinframe;
5628
5629 void R_SkinFrame_PrepareForPurge(void)
5630 {
5631         r_skinframe.loadsequence++;
5632         // wrap it without hitting zero
5633         if (r_skinframe.loadsequence >= 200)
5634                 r_skinframe.loadsequence = 1;
5635 }
5636
5637 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5638 {
5639         if (!skinframe)
5640                 return;
5641         // mark the skinframe as used for the purging code
5642         skinframe->loadsequence = r_skinframe.loadsequence;
5643 }
5644
5645 void R_SkinFrame_Purge(void)
5646 {
5647         int i;
5648         skinframe_t *s;
5649         for (i = 0;i < SKINFRAME_HASH;i++)
5650         {
5651                 for (s = r_skinframe.hash[i];s;s = s->next)
5652                 {
5653                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5654                         {
5655                                 if (s->merged == s->base)
5656                                         s->merged = NULL;
5657                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5658                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5659                                 R_PurgeTexture(s->merged);s->merged = NULL;
5660                                 R_PurgeTexture(s->base  );s->base   = NULL;
5661                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5662                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5663                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5664                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5665                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5666                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5667                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
5668                                 s->loadsequence = 0;
5669                         }
5670                 }
5671         }
5672 }
5673
5674 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5675         skinframe_t *item;
5676         char basename[MAX_QPATH];
5677
5678         Image_StripImageExtension(name, basename, sizeof(basename));
5679
5680         if( last == NULL ) {
5681                 int hashindex;
5682                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5683                 item = r_skinframe.hash[hashindex];
5684         } else {
5685                 item = last->next;
5686         }
5687
5688         // linearly search through the hash bucket
5689         for( ; item ; item = item->next ) {
5690                 if( !strcmp( item->basename, basename ) ) {
5691                         return item;
5692                 }
5693         }
5694         return NULL;
5695 }
5696
5697 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5698 {
5699         skinframe_t *item;
5700         int hashindex;
5701         char basename[MAX_QPATH];
5702
5703         Image_StripImageExtension(name, basename, sizeof(basename));
5704
5705         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5706         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5707                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5708                         break;
5709
5710         if (!item) {
5711                 rtexture_t *dyntexture;
5712                 // check whether its a dynamic texture
5713                 dyntexture = CL_GetDynTexture( basename );
5714                 if (!add && !dyntexture)
5715                         return NULL;
5716                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5717                 memset(item, 0, sizeof(*item));
5718                 strlcpy(item->basename, basename, sizeof(item->basename));
5719                 item->base = dyntexture; // either NULL or dyntexture handle
5720                 item->textureflags = textureflags;
5721                 item->comparewidth = comparewidth;
5722                 item->compareheight = compareheight;
5723                 item->comparecrc = comparecrc;
5724                 item->next = r_skinframe.hash[hashindex];
5725                 r_skinframe.hash[hashindex] = item;
5726         }
5727         else if( item->base == NULL )
5728         {
5729                 rtexture_t *dyntexture;
5730                 // check whether its a dynamic texture
5731                 // 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]
5732                 dyntexture = CL_GetDynTexture( basename );
5733                 item->base = dyntexture; // either NULL or dyntexture handle
5734         }
5735
5736         R_SkinFrame_MarkUsed(item);
5737         return item;
5738 }
5739
5740 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5741         { \
5742                 unsigned long long avgcolor[5], wsum; \
5743                 int pix, comp, w; \
5744                 avgcolor[0] = 0; \
5745                 avgcolor[1] = 0; \
5746                 avgcolor[2] = 0; \
5747                 avgcolor[3] = 0; \
5748                 avgcolor[4] = 0; \
5749                 wsum = 0; \
5750                 for(pix = 0; pix < cnt; ++pix) \
5751                 { \
5752                         w = 0; \
5753                         for(comp = 0; comp < 3; ++comp) \
5754                                 w += getpixel; \
5755                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5756                         { \
5757                                 ++wsum; \
5758                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5759                                 w = getpixel; \
5760                                 for(comp = 0; comp < 3; ++comp) \
5761                                         avgcolor[comp] += getpixel * w; \
5762                                 avgcolor[3] += w; \
5763                         } \
5764                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5765                         avgcolor[4] += getpixel; \
5766                 } \
5767                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5768                         avgcolor[3] = 1; \
5769                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5770                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5771                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5772                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5773         }
5774
5775 extern cvar_t gl_picmip;
5776 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5777 {
5778         int j;
5779         unsigned char *pixels;
5780         unsigned char *bumppixels;
5781         unsigned char *basepixels = NULL;
5782         int basepixels_width = 0;
5783         int basepixels_height = 0;
5784         skinframe_t *skinframe;
5785         rtexture_t *ddsbase = NULL;
5786         qboolean ddshasalpha = false;
5787         float ddsavgcolor[4];
5788         char basename[MAX_QPATH];
5789         int miplevel = R_PicmipForFlags(textureflags);
5790         int savemiplevel = miplevel;
5791         int mymiplevel;
5792
5793         if (cls.state == ca_dedicated)
5794                 return NULL;
5795
5796         // return an existing skinframe if already loaded
5797         // if loading of the first image fails, don't make a new skinframe as it
5798         // would cause all future lookups of this to be missing
5799         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5800         if (skinframe && skinframe->base)
5801                 return skinframe;
5802
5803         Image_StripImageExtension(name, basename, sizeof(basename));
5804
5805         // check for DDS texture file first
5806         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
5807         {
5808                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer, &miplevel);
5809                 if (basepixels == NULL)
5810                         return NULL;
5811         }
5812
5813         // FIXME handle miplevel
5814
5815         if (developer_loading.integer)
5816                 Con_Printf("loading skin \"%s\"\n", name);
5817
5818         // we've got some pixels to store, so really allocate this new texture now
5819         if (!skinframe)
5820                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5821         skinframe->stain = NULL;
5822         skinframe->merged = NULL;
5823         skinframe->base = NULL;
5824         skinframe->pants = NULL;
5825         skinframe->shirt = NULL;
5826         skinframe->nmap = NULL;
5827         skinframe->gloss = NULL;
5828         skinframe->glow = NULL;
5829         skinframe->fog = NULL;
5830         skinframe->reflect = NULL;
5831         skinframe->hasalpha = false;
5832
5833         if (ddsbase)
5834         {
5835                 skinframe->base = ddsbase;
5836                 skinframe->hasalpha = ddshasalpha;
5837                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5838                 if (r_loadfog && skinframe->hasalpha)
5839                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
5840                 //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]);
5841         }
5842         else
5843         {
5844                 basepixels_width = image_width;
5845                 basepixels_height = image_height;
5846                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
5847                 if (textureflags & TEXF_ALPHA)
5848                 {
5849                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5850                         {
5851                                 if (basepixels[j] < 255)
5852                                 {
5853                                         skinframe->hasalpha = true;
5854                                         break;
5855                                 }
5856                         }
5857                         if (r_loadfog && skinframe->hasalpha)
5858                         {
5859                                 // has transparent pixels
5860                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5861                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5862                                 {
5863                                         pixels[j+0] = 255;
5864                                         pixels[j+1] = 255;
5865                                         pixels[j+2] = 255;
5866                                         pixels[j+3] = basepixels[j+3];
5867                                 }
5868                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
5869                                 Mem_Free(pixels);
5870                         }
5871                 }
5872                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5873                 //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]);
5874                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5875                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
5876                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5877                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
5878         }
5879
5880         if (r_loaddds)
5881         {
5882                 mymiplevel = savemiplevel;
5883                 if (r_loadnormalmap)
5884                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
5885                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5886                 if (r_loadgloss)
5887                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5888                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5889                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5890                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5891         }
5892
5893         // _norm is the name used by tenebrae and has been adopted as standard
5894         if (r_loadnormalmap && skinframe->nmap == NULL)
5895         {
5896                 mymiplevel = savemiplevel;
5897                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
5898                 {
5899                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
5900                         Mem_Free(pixels);
5901                         pixels = NULL;
5902                 }
5903                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
5904                 {
5905                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5906                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5907                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
5908                         Mem_Free(pixels);
5909                         Mem_Free(bumppixels);
5910                 }
5911                 else if (r_shadow_bumpscale_basetexture.value > 0)
5912                 {
5913                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5914                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5915                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
5916                         Mem_Free(pixels);
5917                 }
5918                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5919                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
5920         }
5921
5922         // _luma is supported only for tenebrae compatibility
5923         // _glow is the preferred name
5924         mymiplevel = savemiplevel;
5925         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel))))
5926         {
5927                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
5928                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5929                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
5930                 Mem_Free(pixels);pixels = NULL;
5931         }
5932
5933         mymiplevel = savemiplevel;
5934         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)))
5935         {
5936                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
5937                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5938                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
5939                 Mem_Free(pixels);
5940                 pixels = NULL;
5941         }
5942
5943         mymiplevel = savemiplevel;
5944         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)))
5945         {
5946                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
5947                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5948                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
5949                 Mem_Free(pixels);
5950                 pixels = NULL;
5951         }
5952
5953         mymiplevel = savemiplevel;
5954         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)))
5955         {
5956                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
5957                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5958                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
5959                 Mem_Free(pixels);
5960                 pixels = NULL;
5961         }
5962
5963         mymiplevel = savemiplevel;
5964         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)))
5965         {
5966                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
5967                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
5968                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
5969                 Mem_Free(pixels);
5970                 pixels = NULL;
5971         }
5972
5973         if (basepixels)
5974                 Mem_Free(basepixels);
5975
5976         return skinframe;
5977 }
5978
5979 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5980 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5981 {
5982         int i;
5983         unsigned char *temp1, *temp2;
5984         skinframe_t *skinframe;
5985
5986         if (cls.state == ca_dedicated)
5987                 return NULL;
5988
5989         // if already loaded just return it, otherwise make a new skinframe
5990         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5991         if (skinframe && skinframe->base)
5992                 return skinframe;
5993
5994         skinframe->stain = NULL;
5995         skinframe->merged = NULL;
5996         skinframe->base = NULL;
5997         skinframe->pants = NULL;
5998         skinframe->shirt = NULL;
5999         skinframe->nmap = NULL;
6000         skinframe->gloss = NULL;
6001         skinframe->glow = NULL;
6002         skinframe->fog = NULL;
6003         skinframe->reflect = NULL;
6004         skinframe->hasalpha = false;
6005
6006         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6007         if (!skindata)
6008                 return NULL;
6009
6010         if (developer_loading.integer)
6011                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6012
6013         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6014         {
6015                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6016                 temp2 = temp1 + width * height * 4;
6017                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6018                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
6019                 Mem_Free(temp1);
6020         }
6021         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6022         if (textureflags & TEXF_ALPHA)
6023         {
6024                 for (i = 3;i < width * height * 4;i += 4)
6025                 {
6026                         if (skindata[i] < 255)
6027                         {
6028                                 skinframe->hasalpha = true;
6029                                 break;
6030                         }
6031                 }
6032                 if (r_loadfog && skinframe->hasalpha)
6033                 {
6034                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6035                         memcpy(fogpixels, skindata, width * height * 4);
6036                         for (i = 0;i < width * height * 4;i += 4)
6037                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6038                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6039                         Mem_Free(fogpixels);
6040                 }
6041         }
6042
6043         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6044         //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]);
6045
6046         return skinframe;
6047 }
6048
6049 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6050 {
6051         int i;
6052         int featuresmask;
6053         skinframe_t *skinframe;
6054
6055         if (cls.state == ca_dedicated)
6056                 return NULL;
6057
6058         // if already loaded just return it, otherwise make a new skinframe
6059         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6060         if (skinframe && skinframe->base)
6061                 return skinframe;
6062
6063         skinframe->stain = NULL;
6064         skinframe->merged = NULL;
6065         skinframe->base = NULL;
6066         skinframe->pants = NULL;
6067         skinframe->shirt = NULL;
6068         skinframe->nmap = NULL;
6069         skinframe->gloss = NULL;
6070         skinframe->glow = NULL;
6071         skinframe->fog = NULL;
6072         skinframe->reflect = NULL;
6073         skinframe->hasalpha = false;
6074
6075         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6076         if (!skindata)
6077                 return NULL;
6078
6079         if (developer_loading.integer)
6080                 Con_Printf("loading quake skin \"%s\"\n", name);
6081
6082         // 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)
6083         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
6084         memcpy(skinframe->qpixels, skindata, width*height);
6085         skinframe->qwidth = width;
6086         skinframe->qheight = height;
6087
6088         featuresmask = 0;
6089         for (i = 0;i < width * height;i++)
6090                 featuresmask |= palette_featureflags[skindata[i]];
6091
6092         skinframe->hasalpha = false;
6093         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6094         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6095         skinframe->qgeneratemerged = true;
6096         skinframe->qgeneratebase = skinframe->qhascolormapping;
6097         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6098
6099         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6100         //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]);
6101
6102         return skinframe;
6103 }
6104
6105 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6106 {
6107         int width;
6108         int height;
6109         unsigned char *skindata;
6110
6111         if (!skinframe->qpixels)
6112                 return;
6113
6114         if (!skinframe->qhascolormapping)
6115                 colormapped = false;
6116
6117         if (colormapped)
6118         {
6119                 if (!skinframe->qgeneratebase)
6120                         return;
6121         }
6122         else
6123         {
6124                 if (!skinframe->qgeneratemerged)
6125                         return;
6126         }
6127
6128         width = skinframe->qwidth;
6129         height = skinframe->qheight;
6130         skindata = skinframe->qpixels;
6131
6132         if (skinframe->qgeneratenmap)
6133         {
6134                 unsigned char *temp1, *temp2;
6135                 skinframe->qgeneratenmap = false;
6136                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6137                 temp2 = temp1 + width * height * 4;
6138                 // use either a custom palette or the quake palette
6139                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6140                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6141                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
6142                 Mem_Free(temp1);
6143         }
6144
6145         if (skinframe->qgenerateglow)
6146         {
6147                 skinframe->qgenerateglow = false;
6148                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6149         }
6150
6151         if (colormapped)
6152         {
6153                 skinframe->qgeneratebase = false;
6154                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
6155                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6156                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6157         }
6158         else
6159         {
6160                 skinframe->qgeneratemerged = false;
6161                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
6162         }
6163
6164         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6165         {
6166                 Mem_Free(skinframe->qpixels);
6167                 skinframe->qpixels = NULL;
6168         }
6169 }
6170
6171 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)
6172 {
6173         int i;
6174         skinframe_t *skinframe;
6175
6176         if (cls.state == ca_dedicated)
6177                 return NULL;
6178
6179         // if already loaded just return it, otherwise make a new skinframe
6180         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6181         if (skinframe && skinframe->base)
6182                 return skinframe;
6183
6184         skinframe->stain = NULL;
6185         skinframe->merged = NULL;
6186         skinframe->base = NULL;
6187         skinframe->pants = NULL;
6188         skinframe->shirt = NULL;
6189         skinframe->nmap = NULL;
6190         skinframe->gloss = NULL;
6191         skinframe->glow = NULL;
6192         skinframe->fog = NULL;
6193         skinframe->reflect = NULL;
6194         skinframe->hasalpha = false;
6195
6196         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6197         if (!skindata)
6198                 return NULL;
6199
6200         if (developer_loading.integer)
6201                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6202
6203         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6204         if (textureflags & TEXF_ALPHA)
6205         {
6206                 for (i = 0;i < width * height;i++)
6207                 {
6208                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6209                         {
6210                                 skinframe->hasalpha = true;
6211                                 break;
6212                         }
6213                 }
6214                 if (r_loadfog && skinframe->hasalpha)
6215                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6216         }
6217
6218         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6219         //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]);
6220
6221         return skinframe;
6222 }
6223
6224 skinframe_t *R_SkinFrame_LoadMissing(void)
6225 {
6226         skinframe_t *skinframe;
6227
6228         if (cls.state == ca_dedicated)
6229                 return NULL;
6230
6231         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6232         skinframe->stain = NULL;
6233         skinframe->merged = NULL;
6234         skinframe->base = NULL;
6235         skinframe->pants = NULL;
6236         skinframe->shirt = NULL;
6237         skinframe->nmap = NULL;
6238         skinframe->gloss = NULL;
6239         skinframe->glow = NULL;
6240         skinframe->fog = NULL;
6241         skinframe->reflect = NULL;
6242         skinframe->hasalpha = false;
6243
6244         skinframe->avgcolor[0] = rand() / RAND_MAX;
6245         skinframe->avgcolor[1] = rand() / RAND_MAX;
6246         skinframe->avgcolor[2] = rand() / RAND_MAX;
6247         skinframe->avgcolor[3] = 1;
6248
6249         return skinframe;
6250 }
6251
6252 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6253 typedef struct suffixinfo_s
6254 {
6255         char *suffix;
6256         qboolean flipx, flipy, flipdiagonal;
6257 }
6258 suffixinfo_t;
6259 static suffixinfo_t suffix[3][6] =
6260 {
6261         {
6262                 {"px",   false, false, false},
6263                 {"nx",   false, false, false},
6264                 {"py",   false, false, false},
6265                 {"ny",   false, false, false},
6266                 {"pz",   false, false, false},
6267                 {"nz",   false, false, false}
6268         },
6269         {
6270                 {"posx", false, false, false},
6271                 {"negx", false, false, false},
6272                 {"posy", false, false, false},
6273                 {"negy", false, false, false},
6274                 {"posz", false, false, false},
6275                 {"negz", false, false, false}
6276         },
6277         {
6278                 {"rt",    true, false,  true},
6279                 {"lf",   false,  true,  true},
6280                 {"ft",    true,  true, false},
6281                 {"bk",   false, false, false},
6282                 {"up",    true, false,  true},
6283                 {"dn",    true, false,  true}
6284         }
6285 };
6286
6287 static int componentorder[4] = {0, 1, 2, 3};
6288
6289 rtexture_t *R_LoadCubemap(const char *basename)
6290 {
6291         int i, j, cubemapsize;
6292         unsigned char *cubemappixels, *image_buffer;
6293         rtexture_t *cubemaptexture;
6294         char name[256];
6295         // must start 0 so the first loadimagepixels has no requested width/height
6296         cubemapsize = 0;
6297         cubemappixels = NULL;
6298         cubemaptexture = NULL;
6299         // keep trying different suffix groups (posx, px, rt) until one loads
6300         for (j = 0;j < 3 && !cubemappixels;j++)
6301         {
6302                 // load the 6 images in the suffix group
6303                 for (i = 0;i < 6;i++)
6304                 {
6305                         // generate an image name based on the base and and suffix
6306                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6307                         // load it
6308                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer, NULL)))
6309                         {
6310                                 // an image loaded, make sure width and height are equal
6311                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6312                                 {
6313                                         // if this is the first image to load successfully, allocate the cubemap memory
6314                                         if (!cubemappixels && image_width >= 1)
6315                                         {
6316                                                 cubemapsize = image_width;
6317                                                 // note this clears to black, so unavailable sides are black
6318                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6319                                         }
6320                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6321                                         if (cubemappixels)
6322                                                 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
6323                                 }
6324                                 else
6325                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6326                                 // free the image
6327                                 Mem_Free(image_buffer);
6328                         }
6329                 }
6330         }
6331         // if a cubemap loaded, upload it
6332         if (cubemappixels)
6333         {
6334                 if (developer_loading.integer)
6335                         Con_Printf("loading cubemap \"%s\"\n", basename);
6336
6337                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6338                 Mem_Free(cubemappixels);
6339         }
6340         else
6341         {
6342                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6343                 if (developer_loading.integer)
6344                 {
6345                         Con_Printf("(tried tried images ");
6346                         for (j = 0;j < 3;j++)
6347                                 for (i = 0;i < 6;i++)
6348                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6349                         Con_Print(" and was unable to find any of them).\n");
6350                 }
6351         }
6352         return cubemaptexture;
6353 }
6354
6355 rtexture_t *R_GetCubemap(const char *basename)
6356 {
6357         int i;
6358         for (i = 0;i < r_texture_numcubemaps;i++)
6359                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6360                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6361         if (i >= MAX_CUBEMAPS)
6362                 return r_texture_whitecube;
6363         r_texture_numcubemaps++;
6364         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6365         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6366         return r_texture_cubemaps[i].texture;
6367 }
6368
6369 void R_FreeCubemaps(void)
6370 {
6371         int i;
6372         for (i = 0;i < r_texture_numcubemaps;i++)
6373         {
6374                 if (developer_loading.integer)
6375                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6376                 if (r_texture_cubemaps[i].texture)
6377                         R_FreeTexture(r_texture_cubemaps[i].texture);
6378         }
6379         r_texture_numcubemaps = 0;
6380 }
6381
6382 void R_Main_FreeViewCache(void)
6383 {
6384         if (r_refdef.viewcache.entityvisible)
6385                 Mem_Free(r_refdef.viewcache.entityvisible);
6386         if (r_refdef.viewcache.world_pvsbits)
6387                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6388         if (r_refdef.viewcache.world_leafvisible)
6389                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6390         if (r_refdef.viewcache.world_surfacevisible)
6391                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6392         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6393 }
6394
6395 void R_Main_ResizeViewCache(void)
6396 {
6397         int numentities = r_refdef.scene.numentities;
6398         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6399         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6400         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6401         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6402         if (r_refdef.viewcache.maxentities < numentities)
6403         {
6404                 r_refdef.viewcache.maxentities = numentities;
6405                 if (r_refdef.viewcache.entityvisible)
6406                         Mem_Free(r_refdef.viewcache.entityvisible);
6407                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6408         }
6409         if (r_refdef.viewcache.world_numclusters != numclusters)
6410         {
6411                 r_refdef.viewcache.world_numclusters = numclusters;
6412                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6413                 if (r_refdef.viewcache.world_pvsbits)
6414                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6415                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6416         }
6417         if (r_refdef.viewcache.world_numleafs != numleafs)
6418         {
6419                 r_refdef.viewcache.world_numleafs = numleafs;
6420                 if (r_refdef.viewcache.world_leafvisible)
6421                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6422                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6423         }
6424         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6425         {
6426                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6427                 if (r_refdef.viewcache.world_surfacevisible)
6428                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6429                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6430         }
6431 }
6432
6433 extern rtexture_t *loadingscreentexture;
6434 void gl_main_start(void)
6435 {
6436         loadingscreentexture = NULL;
6437         r_texture_blanknormalmap = NULL;
6438         r_texture_white = NULL;
6439         r_texture_grey128 = NULL;
6440         r_texture_black = NULL;
6441         r_texture_whitecube = NULL;
6442         r_texture_normalizationcube = NULL;
6443         r_texture_fogattenuation = NULL;
6444         r_texture_fogheighttexture = NULL;
6445         r_texture_gammaramps = NULL;
6446         r_texture_numcubemaps = 0;
6447
6448         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6449         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6450
6451         switch(vid.renderpath)
6452         {
6453         case RENDERPATH_GL20:
6454         case RENDERPATH_CGGL:
6455                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6456                 Cvar_SetValueQuick(&gl_combine, 1);
6457                 Cvar_SetValueQuick(&r_glsl, 1);
6458                 r_loadnormalmap = true;
6459                 r_loadgloss = true;
6460                 r_loadfog = false;
6461                 break;
6462         case RENDERPATH_GL13:
6463                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6464                 Cvar_SetValueQuick(&gl_combine, 1);
6465                 Cvar_SetValueQuick(&r_glsl, 0);
6466                 r_loadnormalmap = false;
6467                 r_loadgloss = false;
6468                 r_loadfog = true;
6469                 break;
6470         case RENDERPATH_GL11:
6471                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6472                 Cvar_SetValueQuick(&gl_combine, 0);
6473                 Cvar_SetValueQuick(&r_glsl, 0);
6474                 r_loadnormalmap = false;
6475                 r_loadgloss = false;
6476                 r_loadfog = true;
6477                 break;
6478         }
6479
6480         R_AnimCache_Free();
6481         R_FrameData_Reset();
6482
6483         r_numqueries = 0;
6484         r_maxqueries = 0;
6485         memset(r_queries, 0, sizeof(r_queries));
6486
6487         r_qwskincache = NULL;
6488         r_qwskincache_size = 0;
6489
6490         // set up r_skinframe loading system for textures
6491         memset(&r_skinframe, 0, sizeof(r_skinframe));
6492         r_skinframe.loadsequence = 1;
6493         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6494
6495         r_main_texturepool = R_AllocTexturePool();
6496         R_BuildBlankTextures();
6497         R_BuildNoTexture();
6498         if (vid.support.arb_texture_cube_map)
6499         {
6500                 R_BuildWhiteCube();
6501                 R_BuildNormalizationCube();
6502         }
6503         r_texture_fogattenuation = NULL;
6504         r_texture_fogheighttexture = NULL;
6505         r_texture_gammaramps = NULL;
6506         //r_texture_fogintensity = NULL;
6507         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6508         memset(&r_waterstate, 0, sizeof(r_waterstate));
6509         r_glsl_permutation = NULL;
6510         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6511         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6512         glslshaderstring = NULL;
6513 #ifdef SUPPORTCG
6514         r_cg_permutation = NULL;
6515         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6516         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
6517         cgshaderstring = NULL;
6518 #endif
6519         memset(&r_svbsp, 0, sizeof (r_svbsp));
6520
6521         r_refdef.fogmasktable_density = 0;
6522 }
6523
6524 void gl_main_shutdown(void)
6525 {
6526         R_AnimCache_Free();
6527         R_FrameData_Reset();
6528
6529         R_Main_FreeViewCache();
6530
6531         if (r_maxqueries)
6532                 qglDeleteQueriesARB(r_maxqueries, r_queries);
6533
6534         r_numqueries = 0;
6535         r_maxqueries = 0;
6536         memset(r_queries, 0, sizeof(r_queries));
6537
6538         r_qwskincache = NULL;
6539         r_qwskincache_size = 0;
6540
6541         // clear out the r_skinframe state
6542         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6543         memset(&r_skinframe, 0, sizeof(r_skinframe));
6544
6545         if (r_svbsp.nodes)
6546                 Mem_Free(r_svbsp.nodes);
6547         memset(&r_svbsp, 0, sizeof (r_svbsp));
6548         R_FreeTexturePool(&r_main_texturepool);
6549         loadingscreentexture = NULL;
6550         r_texture_blanknormalmap = NULL;
6551         r_texture_white = NULL;
6552         r_texture_grey128 = NULL;
6553         r_texture_black = NULL;
6554         r_texture_whitecube = NULL;
6555         r_texture_normalizationcube = NULL;
6556         r_texture_fogattenuation = NULL;
6557         r_texture_fogheighttexture = NULL;
6558         r_texture_gammaramps = NULL;
6559         r_texture_numcubemaps = 0;
6560         //r_texture_fogintensity = NULL;
6561         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6562         memset(&r_waterstate, 0, sizeof(r_waterstate));
6563         r_glsl_permutation = NULL;
6564         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6565         glslshaderstring = NULL;
6566 #ifdef SUPPORTCG
6567         r_cg_permutation = NULL;
6568         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6569         cgshaderstring = NULL;
6570 #endif
6571         R_GLSL_Restart_f();
6572 }
6573
6574 extern void CL_ParseEntityLump(char *entitystring);
6575 void gl_main_newmap(void)
6576 {
6577         // FIXME: move this code to client
6578         char *entities, entname[MAX_QPATH];
6579         if (r_qwskincache)
6580                 Mem_Free(r_qwskincache);
6581         r_qwskincache = NULL;
6582         r_qwskincache_size = 0;
6583         if (cl.worldmodel)
6584         {
6585                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
6586                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6587                 {
6588                         CL_ParseEntityLump(entities);
6589                         Mem_Free(entities);
6590                         return;
6591                 }
6592                 if (cl.worldmodel->brush.entities)
6593                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
6594         }
6595         R_Main_FreeViewCache();
6596
6597         R_FrameData_Reset();
6598 }
6599
6600 void GL_Main_Init(void)
6601 {
6602         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6603
6604         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6605         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6606         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6607         if (gamemode == GAME_NEHAHRA)
6608         {
6609                 Cvar_RegisterVariable (&gl_fogenable);
6610                 Cvar_RegisterVariable (&gl_fogdensity);
6611                 Cvar_RegisterVariable (&gl_fogred);
6612                 Cvar_RegisterVariable (&gl_foggreen);
6613                 Cvar_RegisterVariable (&gl_fogblue);
6614                 Cvar_RegisterVariable (&gl_fogstart);
6615                 Cvar_RegisterVariable (&gl_fogend);
6616                 Cvar_RegisterVariable (&gl_skyclip);
6617         }
6618         Cvar_RegisterVariable(&r_motionblur);
6619         Cvar_RegisterVariable(&r_motionblur_maxblur);
6620         Cvar_RegisterVariable(&r_motionblur_bmin);
6621         Cvar_RegisterVariable(&r_motionblur_vmin);
6622         Cvar_RegisterVariable(&r_motionblur_vmax);
6623         Cvar_RegisterVariable(&r_motionblur_vcoeff);
6624         Cvar_RegisterVariable(&r_motionblur_randomize);
6625         Cvar_RegisterVariable(&r_damageblur);
6626         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6627         Cvar_RegisterVariable(&r_equalize_entities_minambient);
6628         Cvar_RegisterVariable(&r_equalize_entities_by);
6629         Cvar_RegisterVariable(&r_equalize_entities_to);
6630         Cvar_RegisterVariable(&r_depthfirst);
6631         Cvar_RegisterVariable(&r_useinfinitefarclip);
6632         Cvar_RegisterVariable(&r_farclip_base);
6633         Cvar_RegisterVariable(&r_farclip_world);
6634         Cvar_RegisterVariable(&r_nearclip);
6635         Cvar_RegisterVariable(&r_showbboxes);
6636         Cvar_RegisterVariable(&r_showsurfaces);
6637         Cvar_RegisterVariable(&r_showtris);
6638         Cvar_RegisterVariable(&r_shownormals);
6639         Cvar_RegisterVariable(&r_showlighting);
6640         Cvar_RegisterVariable(&r_showshadowvolumes);
6641         Cvar_RegisterVariable(&r_showcollisionbrushes);
6642         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6643         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6644         Cvar_RegisterVariable(&r_showdisabledepthtest);
6645         Cvar_RegisterVariable(&r_drawportals);
6646         Cvar_RegisterVariable(&r_drawentities);
6647         Cvar_RegisterVariable(&r_draw2d);
6648         Cvar_RegisterVariable(&r_drawworld);
6649         Cvar_RegisterVariable(&r_cullentities_trace);
6650         Cvar_RegisterVariable(&r_cullentities_trace_samples);
6651         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6652         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6653         Cvar_RegisterVariable(&r_cullentities_trace_delay);
6654         Cvar_RegisterVariable(&r_drawviewmodel);
6655         Cvar_RegisterVariable(&r_drawexteriormodel);
6656         Cvar_RegisterVariable(&r_speeds);
6657         Cvar_RegisterVariable(&r_fullbrights);
6658         Cvar_RegisterVariable(&r_wateralpha);
6659         Cvar_RegisterVariable(&r_dynamic);
6660         Cvar_RegisterVariable(&r_fakelight);
6661         Cvar_RegisterVariable(&r_fakelight_intensity);
6662         Cvar_RegisterVariable(&r_fullbright);
6663         Cvar_RegisterVariable(&r_shadows);
6664         Cvar_RegisterVariable(&r_shadows_darken);
6665         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6666         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6667         Cvar_RegisterVariable(&r_shadows_throwdistance);
6668         Cvar_RegisterVariable(&r_shadows_throwdirection);
6669         Cvar_RegisterVariable(&r_shadows_focus);
6670         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6671         Cvar_RegisterVariable(&r_q1bsp_skymasking);
6672         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6673         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6674         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6675         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6676         Cvar_RegisterVariable(&r_fog_exp2);
6677         Cvar_RegisterVariable(&r_drawfog);
6678         Cvar_RegisterVariable(&r_transparentdepthmasking);
6679         Cvar_RegisterVariable(&r_texture_dds_load);
6680         Cvar_RegisterVariable(&r_texture_dds_save);
6681         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6682         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6683         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6684         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6685         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6686         Cvar_RegisterVariable(&r_textureunits);
6687         Cvar_RegisterVariable(&gl_combine);
6688         Cvar_RegisterVariable(&r_glsl);
6689         Cvar_RegisterVariable(&r_glsl_deluxemapping);
6690         Cvar_RegisterVariable(&r_glsl_offsetmapping);
6691         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6692         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6693         Cvar_RegisterVariable(&r_glsl_postprocess);
6694         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6695         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6696         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6697         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6698         Cvar_RegisterVariable(&r_water);
6699         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6700         Cvar_RegisterVariable(&r_water_clippingplanebias);
6701         Cvar_RegisterVariable(&r_water_refractdistort);
6702         Cvar_RegisterVariable(&r_water_reflectdistort);
6703         Cvar_RegisterVariable(&r_water_scissormode);
6704         Cvar_RegisterVariable(&r_lerpsprites);
6705         Cvar_RegisterVariable(&r_lerpmodels);
6706         Cvar_RegisterVariable(&r_lerplightstyles);
6707         Cvar_RegisterVariable(&r_waterscroll);
6708         Cvar_RegisterVariable(&r_bloom);
6709         Cvar_RegisterVariable(&r_bloom_colorscale);
6710         Cvar_RegisterVariable(&r_bloom_brighten);
6711         Cvar_RegisterVariable(&r_bloom_blur);
6712         Cvar_RegisterVariable(&r_bloom_resolution);
6713         Cvar_RegisterVariable(&r_bloom_colorexponent);
6714         Cvar_RegisterVariable(&r_bloom_colorsubtract);
6715         Cvar_RegisterVariable(&r_hdr);
6716         Cvar_RegisterVariable(&r_hdr_scenebrightness);
6717         Cvar_RegisterVariable(&r_hdr_glowintensity);
6718         Cvar_RegisterVariable(&r_hdr_range);
6719         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6720         Cvar_RegisterVariable(&developer_texturelogging);
6721         Cvar_RegisterVariable(&gl_lightmaps);
6722         Cvar_RegisterVariable(&r_test);
6723         Cvar_RegisterVariable(&r_batchmode);
6724         Cvar_RegisterVariable(&r_glsl_saturation);
6725         Cvar_RegisterVariable(&r_framedatasize);
6726         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6727                 Cvar_SetValue("r_fullbrights", 0);
6728         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
6729
6730         Cvar_RegisterVariable(&r_track_sprites);
6731         Cvar_RegisterVariable(&r_track_sprites_flags);
6732         Cvar_RegisterVariable(&r_track_sprites_scalew);
6733         Cvar_RegisterVariable(&r_track_sprites_scaleh);
6734         Cvar_RegisterVariable(&r_overheadsprites_perspective);
6735         Cvar_RegisterVariable(&r_overheadsprites_pushback);
6736 }
6737
6738 extern void R_Textures_Init(void);
6739 extern void GL_Draw_Init(void);
6740 extern void GL_Main_Init(void);
6741 extern void R_Shadow_Init(void);
6742 extern void R_Sky_Init(void);
6743 extern void GL_Surf_Init(void);
6744 extern void R_Particles_Init(void);
6745 extern void R_Explosion_Init(void);
6746 extern void gl_backend_init(void);
6747 extern void Sbar_Init(void);
6748 extern void R_LightningBeams_Init(void);
6749 extern void Mod_RenderInit(void);
6750 extern void Font_Init(void);
6751
6752 void Render_Init(void)
6753 {
6754         gl_backend_init();
6755         R_Textures_Init();
6756         GL_Main_Init();
6757         Font_Init();
6758         GL_Draw_Init();
6759         R_Shadow_Init();
6760         R_Sky_Init();
6761         GL_Surf_Init();
6762         Sbar_Init();
6763         R_Particles_Init();
6764         R_Explosion_Init();
6765         R_LightningBeams_Init();
6766         Mod_RenderInit();
6767 }
6768
6769 /*
6770 ===============
6771 GL_Init
6772 ===============
6773 */
6774 extern char *ENGINE_EXTENSIONS;
6775 void GL_Init (void)
6776 {
6777         gl_renderer = (const char *)qglGetString(GL_RENDERER);
6778         gl_vendor = (const char *)qglGetString(GL_VENDOR);
6779         gl_version = (const char *)qglGetString(GL_VERSION);
6780         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6781
6782         if (!gl_extensions)
6783                 gl_extensions = "";
6784         if (!gl_platformextensions)
6785                 gl_platformextensions = "";
6786
6787         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6788         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6789         Con_Printf("GL_VERSION: %s\n", gl_version);
6790         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6791         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6792
6793         VID_CheckExtensions();
6794
6795         // LordHavoc: report supported extensions
6796         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6797
6798         // clear to black (loading plaque will be seen over this)
6799         CHECKGLERROR
6800         qglClearColor(0,0,0,1);CHECKGLERROR
6801         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6802 }
6803
6804 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6805 {
6806         int i;
6807         mplane_t *p;
6808         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6809         {
6810                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6811                 if (i == 4)
6812                         continue;
6813                 p = r_refdef.view.frustum + i;
6814                 switch(p->signbits)
6815                 {
6816                 default:
6817                 case 0:
6818                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6819                                 return true;
6820                         break;
6821                 case 1:
6822                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6823                                 return true;
6824                         break;
6825                 case 2:
6826                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6827                                 return true;
6828                         break;
6829                 case 3:
6830                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6831                                 return true;
6832                         break;
6833                 case 4:
6834                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6835                                 return true;
6836                         break;
6837                 case 5:
6838                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6839                                 return true;
6840                         break;
6841                 case 6:
6842                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6843                                 return true;
6844                         break;
6845                 case 7:
6846                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6847                                 return true;
6848                         break;
6849                 }
6850         }
6851         return false;
6852 }
6853
6854 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6855 {
6856         int i;
6857         const mplane_t *p;
6858         for (i = 0;i < numplanes;i++)
6859         {
6860                 p = planes + i;
6861                 switch(p->signbits)
6862                 {
6863                 default:
6864                 case 0:
6865                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6866                                 return true;
6867                         break;
6868                 case 1:
6869                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6870                                 return true;
6871                         break;
6872                 case 2:
6873                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6874                                 return true;
6875                         break;
6876                 case 3:
6877                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6878                                 return true;
6879                         break;
6880                 case 4:
6881                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6882                                 return true;
6883                         break;
6884                 case 5:
6885                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6886                                 return true;
6887                         break;
6888                 case 6:
6889                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6890                                 return true;
6891                         break;
6892                 case 7:
6893                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6894                                 return true;
6895                         break;
6896                 }
6897         }
6898         return false;
6899 }
6900
6901 //==================================================================================
6902
6903 // LordHavoc: this stores temporary data used within the same frame
6904
6905 qboolean r_framedata_failed;
6906 static size_t r_framedata_size;
6907 static size_t r_framedata_current;
6908 static void *r_framedata_base;
6909
6910 void R_FrameData_Reset(void)
6911 {
6912         if (r_framedata_base)
6913                 Mem_Free(r_framedata_base);
6914         r_framedata_base = NULL;
6915         r_framedata_size = 0;
6916         r_framedata_current = 0;
6917         r_framedata_failed = false;
6918 }
6919
6920 void R_FrameData_NewFrame(void)
6921 {
6922         size_t wantedsize;
6923         if (r_framedata_failed)
6924                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6925         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6926         wantedsize = bound(65536, wantedsize, 128*1024*1024);
6927         if (r_framedata_size != wantedsize)
6928         {
6929                 r_framedata_size = wantedsize;
6930                 if (r_framedata_base)
6931                         Mem_Free(r_framedata_base);
6932                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6933         }
6934         r_framedata_current = 0;
6935         r_framedata_failed = false;
6936 }
6937
6938 void *R_FrameData_Alloc(size_t size)
6939 {
6940         void *data;
6941
6942         // align to 16 byte boundary
6943         size = (size + 15) & ~15;
6944         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6945         r_framedata_current += size;
6946
6947         // check overflow
6948         if (r_framedata_current > r_framedata_size)
6949                 r_framedata_failed = true;
6950
6951         // return NULL on everything after a failure
6952         if (r_framedata_failed)
6953                 return NULL;
6954
6955         return data;
6956 }
6957
6958 void *R_FrameData_Store(size_t size, void *data)
6959 {
6960         void *d = R_FrameData_Alloc(size);
6961         if (d)
6962                 memcpy(d, data, size);
6963         return d;
6964 }
6965
6966 //==================================================================================
6967
6968 // LordHavoc: animcache originally written by Echon, rewritten since then
6969
6970 /**
6971  * Animation cache prevents re-generating mesh data for an animated model
6972  * multiple times in one frame for lighting, shadowing, reflections, etc.
6973  */
6974
6975 void R_AnimCache_Free(void)
6976 {
6977 }
6978
6979 void R_AnimCache_ClearCache(void)
6980 {
6981         int i;
6982         entity_render_t *ent;
6983
6984         for (i = 0;i < r_refdef.scene.numentities;i++)
6985         {
6986                 ent = r_refdef.scene.entities[i];
6987                 ent->animcache_vertex3f = NULL;
6988                 ent->animcache_normal3f = NULL;
6989                 ent->animcache_svector3f = NULL;
6990                 ent->animcache_tvector3f = NULL;
6991         }
6992 }
6993
6994 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6995 {
6996         dp_model_t *model = ent->model;
6997         int numvertices;
6998         // see if it's already cached this frame
6999         if (ent->animcache_vertex3f)
7000         {
7001                 // add normals/tangents if needed
7002                 if (wantnormals || wanttangents)
7003                 {
7004                         if (ent->animcache_normal3f)
7005                                 wantnormals = false;
7006                         if (ent->animcache_svector3f)
7007                                 wanttangents = false;
7008                         if (wantnormals || wanttangents)
7009                         {
7010                                 numvertices = model->surfmesh.num_vertices;
7011                                 if (wantnormals)
7012                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
7013                                 if (wanttangents)
7014                                 {
7015                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
7016                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
7017                                 }
7018                                 if (!r_framedata_failed)
7019                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7020                         }
7021                 }
7022         }
7023         else
7024         {
7025                 // see if this ent is worth caching
7026                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7027                         return false;
7028                 // get some memory for this entity and generate mesh data
7029                 numvertices = model->surfmesh.num_vertices;
7030                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
7031                 if (wantnormals)
7032                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
7033                 if (wanttangents)
7034                 {
7035                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
7036                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
7037                 }
7038                 if (!r_framedata_failed)
7039                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7040         }
7041         return !r_framedata_failed;
7042 }
7043
7044 void R_AnimCache_CacheVisibleEntities(void)
7045 {
7046         int i;
7047         qboolean wantnormals = !r_showsurfaces.integer;
7048         qboolean wanttangents = !r_showsurfaces.integer;
7049
7050         switch(vid.renderpath)
7051         {
7052         case RENDERPATH_GL20:
7053         case RENDERPATH_CGGL:
7054                 break;
7055         case RENDERPATH_GL13:
7056         case RENDERPATH_GL11:
7057                 wanttangents = false;
7058                 break;
7059         }
7060
7061         // TODO: thread this
7062         // NOTE: R_PrepareRTLights() also caches entities
7063
7064         for (i = 0;i < r_refdef.scene.numentities;i++)
7065                 if (r_refdef.viewcache.entityvisible[i])
7066                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7067 }
7068
7069 //==================================================================================
7070
7071 static void R_View_UpdateEntityLighting (void)
7072 {
7073         int i;
7074         entity_render_t *ent;
7075         vec3_t tempdiffusenormal, avg;
7076         vec_t f, fa, fd, fdd;
7077         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7078
7079         for (i = 0;i < r_refdef.scene.numentities;i++)
7080         {
7081                 ent = r_refdef.scene.entities[i];
7082
7083                 // skip unseen models
7084                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7085                         continue;
7086
7087                 // skip bsp models
7088                 if (ent->model && ent->model->brush.num_leafs)
7089                 {
7090                         // TODO: use modellight for r_ambient settings on world?
7091                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7092                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7093                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7094                         continue;
7095                 }
7096
7097                 // fetch the lighting from the worldmodel data
7098                 VectorClear(ent->modellight_ambient);
7099                 VectorClear(ent->modellight_diffuse);
7100                 VectorClear(tempdiffusenormal);
7101                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7102                 {
7103                         vec3_t org;
7104                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7105                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7106                         if(ent->flags & RENDER_EQUALIZE)
7107                         {
7108                                 // first fix up ambient lighting...
7109                                 if(r_equalize_entities_minambient.value > 0)
7110                                 {
7111                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7112                                         if(fd > 0)
7113                                         {
7114                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7115                                                 if(fa < r_equalize_entities_minambient.value * fd)
7116                                                 {
7117                                                         // solve:
7118                                                         //   fa'/fd' = minambient
7119                                                         //   fa'+0.25*fd' = fa+0.25*fd
7120                                                         //   ...
7121                                                         //   fa' = fd' * minambient
7122                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7123                                                         //   ...
7124                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7125                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7126                                                         //   ...
7127                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7128                                                         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
7129                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7130                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7131                                                 }
7132                                         }
7133                                 }
7134
7135                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7136                                 {
7137                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7138                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7139                                         if(f > 0)
7140                                         {
7141                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7142                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7143                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7144                                         }
7145                                 }
7146                         }
7147                 }
7148                 else // highly rare
7149                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7150
7151                 // move the light direction into modelspace coordinates for lighting code
7152                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7153                 if(VectorLength2(ent->modellight_lightdir) == 0)
7154                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7155                 VectorNormalize(ent->modellight_lightdir);
7156         }
7157 }
7158
7159 #define MAX_LINEOFSIGHTTRACES 64
7160
7161 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7162 {
7163         int i;
7164         vec3_t boxmins, boxmaxs;
7165         vec3_t start;
7166         vec3_t end;
7167         dp_model_t *model = r_refdef.scene.worldmodel;
7168
7169         if (!model || !model->brush.TraceLineOfSight)
7170                 return true;
7171
7172         // expand the box a little
7173         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7174         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7175         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7176         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7177         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7178         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7179
7180         // return true if eye is inside enlarged box
7181         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7182                 return true;
7183
7184         // try center
7185         VectorCopy(eye, start);
7186         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7187         if (model->brush.TraceLineOfSight(model, start, end))
7188                 return true;
7189
7190         // try various random positions
7191         for (i = 0;i < numsamples;i++)
7192         {
7193                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7194                 if (model->brush.TraceLineOfSight(model, start, end))
7195                         return true;
7196         }
7197
7198         return false;
7199 }
7200
7201
7202 static void R_View_UpdateEntityVisible (void)
7203 {
7204         int i;
7205         int renderimask;
7206         int samples;
7207         entity_render_t *ent;
7208
7209         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7210                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7211                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
7212                 :                                                          RENDER_EXTERIORMODEL;
7213         if (!r_drawviewmodel.integer)
7214                 renderimask |= RENDER_VIEWMODEL;
7215         if (!r_drawexteriormodel.integer)
7216                 renderimask |= RENDER_EXTERIORMODEL;
7217         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7218         {
7219                 // worldmodel can check visibility
7220                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7221                 for (i = 0;i < r_refdef.scene.numentities;i++)
7222                 {
7223                         ent = r_refdef.scene.entities[i];
7224                         if (!(ent->flags & renderimask))
7225                         if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
7226                         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))
7227                                 r_refdef.viewcache.entityvisible[i] = true;
7228                 }
7229                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7230                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7231                 {
7232                         for (i = 0;i < r_refdef.scene.numentities;i++)
7233                         {
7234                                 ent = r_refdef.scene.entities[i];
7235                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7236                                 {
7237                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7238                                         if (samples < 0)
7239                                                 continue; // temp entities do pvs only
7240                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7241                                                 ent->last_trace_visibility = realtime;
7242                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7243                                                 r_refdef.viewcache.entityvisible[i] = 0;
7244                                 }
7245                         }
7246                 }
7247         }
7248         else
7249         {
7250                 // no worldmodel or it can't check visibility
7251                 for (i = 0;i < r_refdef.scene.numentities;i++)
7252                 {
7253                         ent = r_refdef.scene.entities[i];
7254                         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));
7255                 }
7256         }
7257 }
7258
7259 /// only used if skyrendermasked, and normally returns false
7260 int R_DrawBrushModelsSky (void)
7261 {
7262         int i, sky;
7263         entity_render_t *ent;
7264
7265         sky = false;
7266         for (i = 0;i < r_refdef.scene.numentities;i++)
7267         {
7268                 if (!r_refdef.viewcache.entityvisible[i])
7269                         continue;
7270                 ent = r_refdef.scene.entities[i];
7271                 if (!ent->model || !ent->model->DrawSky)
7272                         continue;
7273                 ent->model->DrawSky(ent);
7274                 sky = true;
7275         }
7276         return sky;
7277 }
7278
7279 static void R_DrawNoModel(entity_render_t *ent);
7280 static void R_DrawModels(void)
7281 {
7282         int i;
7283         entity_render_t *ent;
7284
7285         for (i = 0;i < r_refdef.scene.numentities;i++)
7286         {
7287                 if (!r_refdef.viewcache.entityvisible[i])
7288                         continue;
7289                 ent = r_refdef.scene.entities[i];
7290                 r_refdef.stats.entities++;
7291                 if (ent->model && ent->model->Draw != NULL)
7292                         ent->model->Draw(ent);
7293                 else
7294                         R_DrawNoModel(ent);
7295         }
7296 }
7297
7298 static void R_DrawModelsDepth(void)
7299 {
7300         int i;
7301         entity_render_t *ent;
7302
7303         for (i = 0;i < r_refdef.scene.numentities;i++)
7304         {
7305                 if (!r_refdef.viewcache.entityvisible[i])
7306                         continue;
7307                 ent = r_refdef.scene.entities[i];
7308                 if (ent->model && ent->model->DrawDepth != NULL)
7309                         ent->model->DrawDepth(ent);
7310         }
7311 }
7312
7313 static void R_DrawModelsDebug(void)
7314 {
7315         int i;
7316         entity_render_t *ent;
7317
7318         for (i = 0;i < r_refdef.scene.numentities;i++)
7319         {
7320                 if (!r_refdef.viewcache.entityvisible[i])
7321                         continue;
7322                 ent = r_refdef.scene.entities[i];
7323                 if (ent->model && ent->model->DrawDebug != NULL)
7324                         ent->model->DrawDebug(ent);
7325         }
7326 }
7327
7328 static void R_DrawModelsAddWaterPlanes(void)
7329 {
7330         int i;
7331         entity_render_t *ent;
7332
7333         for (i = 0;i < r_refdef.scene.numentities;i++)
7334         {
7335                 if (!r_refdef.viewcache.entityvisible[i])
7336                         continue;
7337                 ent = r_refdef.scene.entities[i];
7338                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7339                         ent->model->DrawAddWaterPlanes(ent);
7340         }
7341 }
7342
7343 static void R_View_SetFrustum(const int *scissor)
7344 {
7345         int i;
7346         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
7347         vec3_t forward, left, up, origin, v;
7348
7349         if(scissor)
7350         {
7351                 // flipped x coordinates (because x points left here)
7352                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7353                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7354
7355                 // non-flipped y coordinates
7356                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7357                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7358         }
7359
7360         // we can't trust r_refdef.view.forward and friends in reflected scenes
7361         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7362
7363 #if 0
7364         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7365         r_refdef.view.frustum[0].normal[1] = 0 - 0;
7366         r_refdef.view.frustum[0].normal[2] = -1 - 0;
7367         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7368         r_refdef.view.frustum[1].normal[1] = 0 + 0;
7369         r_refdef.view.frustum[1].normal[2] = -1 + 0;
7370         r_refdef.view.frustum[2].normal[0] = 0 - 0;
7371         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7372         r_refdef.view.frustum[2].normal[2] = -1 - 0;
7373         r_refdef.view.frustum[3].normal[0] = 0 + 0;
7374         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7375         r_refdef.view.frustum[3].normal[2] = -1 + 0;
7376 #endif
7377
7378 #if 0
7379         zNear = r_refdef.nearclip;
7380         nudge = 1.0 - 1.0 / (1<<23);
7381         r_refdef.view.frustum[4].normal[0] = 0 - 0;
7382         r_refdef.view.frustum[4].normal[1] = 0 - 0;
7383         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7384         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7385         r_refdef.view.frustum[5].normal[0] = 0 + 0;
7386         r_refdef.view.frustum[5].normal[1] = 0 + 0;
7387         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7388         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7389 #endif
7390
7391
7392
7393 #if 0
7394         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7395         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7396         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7397         r_refdef.view.frustum[0].dist = m[15] - m[12];
7398
7399         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7400         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7401         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7402         r_refdef.view.frustum[1].dist = m[15] + m[12];
7403
7404         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7405         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7406         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7407         r_refdef.view.frustum[2].dist = m[15] - m[13];
7408
7409         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7410         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7411         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7412         r_refdef.view.frustum[3].dist = m[15] + m[13];
7413
7414         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7415         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7416         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7417         r_refdef.view.frustum[4].dist = m[15] - m[14];
7418
7419         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7420         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7421         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7422         r_refdef.view.frustum[5].dist = m[15] + m[14];
7423 #endif
7424
7425         if (r_refdef.view.useperspective)
7426         {
7427                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7428                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
7429                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
7430                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
7431                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
7432
7433                 // then the normals from the corners relative to origin
7434                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
7435                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
7436                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
7437                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
7438
7439                 // in a NORMAL view, forward cross left == up
7440                 // in a REFLECTED view, forward cross left == down
7441                 // so our cross products above need to be adjusted for a left handed coordinate system
7442                 CrossProduct(forward, left, v);
7443                 if(DotProduct(v, up) < 0)
7444                 {
7445                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
7446                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
7447                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
7448                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
7449                 }
7450
7451                 // Leaving those out was a mistake, those were in the old code, and they
7452                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7453                 // I couldn't reproduce it after adding those normalizations. --blub
7454                 VectorNormalize(r_refdef.view.frustum[0].normal);
7455                 VectorNormalize(r_refdef.view.frustum[1].normal);
7456                 VectorNormalize(r_refdef.view.frustum[2].normal);
7457                 VectorNormalize(r_refdef.view.frustum[3].normal);
7458
7459                 // make the corners absolute
7460                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
7461                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
7462                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
7463                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
7464
7465                 // one more normal
7466                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7467
7468                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7469                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7470                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7471                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7472                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7473         }
7474         else
7475         {
7476                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7477                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7478                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7479                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7480                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7481                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7482                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7483                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7484                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7485                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7486         }
7487         r_refdef.view.numfrustumplanes = 5;
7488
7489         if (r_refdef.view.useclipplane)
7490         {
7491                 r_refdef.view.numfrustumplanes = 6;
7492                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7493         }
7494
7495         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7496                 PlaneClassify(r_refdef.view.frustum + i);
7497
7498         // LordHavoc: note to all quake engine coders, Quake had a special case
7499         // for 90 degrees which assumed a square view (wrong), so I removed it,
7500         // Quake2 has it disabled as well.
7501
7502         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7503         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7504         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7505         //PlaneClassify(&frustum[0]);
7506
7507         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7508         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7509         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7510         //PlaneClassify(&frustum[1]);
7511
7512         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7513         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7514         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7515         //PlaneClassify(&frustum[2]);
7516
7517         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7518         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7519         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7520         //PlaneClassify(&frustum[3]);
7521
7522         // nearclip plane
7523         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7524         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7525         //PlaneClassify(&frustum[4]);
7526 }
7527
7528 void R_View_UpdateWithScissor(const int *myscissor)
7529 {
7530         R_Main_ResizeViewCache();
7531         R_View_SetFrustum(myscissor);
7532         R_View_WorldVisibility(r_refdef.view.useclipplane);
7533         R_View_UpdateEntityVisible();
7534         R_View_UpdateEntityLighting();
7535 }
7536
7537 void R_View_Update(void)
7538 {
7539         R_Main_ResizeViewCache();
7540         R_View_SetFrustum(NULL);
7541         R_View_WorldVisibility(r_refdef.view.useclipplane);
7542         R_View_UpdateEntityVisible();
7543         R_View_UpdateEntityLighting();
7544 }
7545
7546 void R_SetupView(qboolean allowwaterclippingplane)
7547 {
7548         const float *customclipplane = NULL;
7549         float plane[4];
7550         if (r_refdef.view.useclipplane && allowwaterclippingplane)
7551         {
7552                 // LordHavoc: couldn't figure out how to make this approach the
7553                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7554                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7555                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7556                         dist = r_refdef.view.clipplane.dist;
7557                 plane[0] = r_refdef.view.clipplane.normal[0];
7558                 plane[1] = r_refdef.view.clipplane.normal[1];
7559                 plane[2] = r_refdef.view.clipplane.normal[2];
7560                 plane[3] = dist;
7561                 customclipplane = plane;
7562         }
7563
7564         if (!r_refdef.view.useperspective)
7565                 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);
7566         else if (vid.stencil && r_useinfinitefarclip.integer)
7567                 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);
7568         else
7569                 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);
7570         R_SetViewport(&r_refdef.view.viewport);
7571 }
7572
7573 void R_EntityMatrix(const matrix4x4_t *matrix)
7574 {
7575         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7576         {
7577                 gl_modelmatrixchanged = false;
7578                 gl_modelmatrix = *matrix;
7579                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7580                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7581                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7582                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7583                 CHECKGLERROR
7584                 switch(vid.renderpath)
7585                 {
7586                 case RENDERPATH_GL20:
7587                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7588                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7589                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7590                         break;
7591                 case RENDERPATH_CGGL:
7592 #ifdef SUPPORTCG
7593                         CHECKCGERROR
7594                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
7595                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
7596                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7597 #endif
7598                         break;
7599                 case RENDERPATH_GL13:
7600                 case RENDERPATH_GL11:
7601                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7602                         break;
7603                 }
7604         }
7605 }
7606
7607 void R_ResetViewRendering2D(void)
7608 {
7609         r_viewport_t viewport;
7610         DrawQ_Finish();
7611
7612         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7613         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);
7614         R_SetViewport(&viewport);
7615         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7616         GL_Color(1, 1, 1, 1);
7617         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7618         GL_BlendFunc(GL_ONE, GL_ZERO);
7619         GL_AlphaTest(false);
7620         GL_ScissorTest(false);
7621         GL_DepthMask(false);
7622         GL_DepthRange(0, 1);
7623         GL_DepthTest(false);
7624         R_EntityMatrix(&identitymatrix);
7625         R_Mesh_ResetTextureState();
7626         GL_PolygonOffset(0, 0);
7627         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7628         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7629         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7630         qglStencilMask(~0);CHECKGLERROR
7631         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7632         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7633         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
7634 }
7635
7636 void R_ResetViewRendering3D(void)
7637 {
7638         DrawQ_Finish();
7639
7640         R_SetupView(true);
7641         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7642         GL_Color(1, 1, 1, 1);
7643         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7644         GL_BlendFunc(GL_ONE, GL_ZERO);
7645         GL_AlphaTest(false);
7646         GL_ScissorTest(true);
7647         GL_DepthMask(true);
7648         GL_DepthRange(0, 1);
7649         GL_DepthTest(true);
7650         R_EntityMatrix(&identitymatrix);
7651         R_Mesh_ResetTextureState();
7652         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7653         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7654         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7655         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7656         qglStencilMask(~0);CHECKGLERROR
7657         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7658         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7659         GL_CullFace(r_refdef.view.cullface_back);
7660 }
7661
7662 /*
7663 ================
7664 R_RenderView_UpdateViewVectors
7665 ================
7666 */
7667 static void R_RenderView_UpdateViewVectors(void)
7668 {
7669         // break apart the view matrix into vectors for various purposes
7670         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7671         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7672         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7673         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7674         // make an inverted copy of the view matrix for tracking sprites
7675         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7676 }
7677
7678 void R_RenderScene(void);
7679 void R_RenderWaterPlanes(void);
7680
7681 static void R_Water_StartFrame(void)
7682 {
7683         int i;
7684         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
7685         r_waterstate_waterplane_t *p;
7686
7687         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
7688                 return;
7689
7690         switch(vid.renderpath)
7691         {
7692         case RENDERPATH_GL20:
7693         case RENDERPATH_CGGL:
7694                 break;
7695         case RENDERPATH_GL13:
7696         case RENDERPATH_GL11:
7697                 return;
7698         }
7699
7700         // set waterwidth and waterheight to the water resolution that will be
7701         // used (often less than the screen resolution for faster rendering)
7702         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
7703         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
7704
7705         // calculate desired texture sizes
7706         // can't use water if the card does not support the texture size
7707         if (!r_water.integer || r_showsurfaces.integer)
7708                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
7709         else if (vid.support.arb_texture_non_power_of_two)
7710         {
7711                 texturewidth = waterwidth;
7712                 textureheight = waterheight;
7713                 camerawidth = waterwidth;
7714                 cameraheight = waterheight;
7715         }
7716         else
7717         {
7718                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
7719                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
7720                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
7721                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
7722         }
7723
7724         // allocate textures as needed
7725         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
7726         {
7727                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7728                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
7729                 {
7730                         if (p->texture_refraction)
7731                                 R_FreeTexture(p->texture_refraction);
7732                         p->texture_refraction = NULL;
7733                         if (p->texture_reflection)
7734                                 R_FreeTexture(p->texture_reflection);
7735                         p->texture_reflection = NULL;
7736                         if (p->texture_camera)
7737                                 R_FreeTexture(p->texture_camera);
7738                         p->texture_camera = NULL;
7739                 }
7740                 memset(&r_waterstate, 0, sizeof(r_waterstate));
7741                 r_waterstate.texturewidth = texturewidth;
7742                 r_waterstate.textureheight = textureheight;
7743                 r_waterstate.camerawidth = camerawidth;
7744                 r_waterstate.cameraheight = cameraheight;
7745         }
7746
7747         if (r_waterstate.texturewidth)
7748         {
7749                 r_waterstate.enabled = true;
7750
7751                 // when doing a reduced render (HDR) we want to use a smaller area
7752                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
7753                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
7754
7755                 // set up variables that will be used in shader setup
7756                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7757                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7758                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7759                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7760         }
7761
7762         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7763         r_waterstate.numwaterplanes = 0;
7764 }
7765
7766 void R_Water_AddWaterPlane(msurface_t *surface)
7767 {
7768         int triangleindex, planeindex;
7769         const int *e;
7770         vec3_t vert[3];
7771         vec3_t normal;
7772         vec3_t center;
7773         mplane_t plane;
7774         int cam_ent;
7775         r_waterstate_waterplane_t *p;
7776         texture_t *t = R_GetCurrentTexture(surface->texture);
7777         cam_ent = t->camera_entity;
7778         if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
7779                 cam_ent = 0;
7780
7781         // just use the first triangle with a valid normal for any decisions
7782         VectorClear(normal);
7783         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
7784         {
7785                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
7786                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
7787                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
7788                 TriangleNormal(vert[0], vert[1], vert[2], normal);
7789                 if (VectorLength2(normal) >= 0.001)
7790                         break;
7791         }
7792
7793         VectorCopy(normal, plane.normal);
7794         VectorNormalize(plane.normal);
7795         plane.dist = DotProduct(vert[0], plane.normal);
7796         PlaneClassify(&plane);
7797         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
7798         {
7799                 // skip backfaces (except if nocullface is set)
7800                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
7801                         return;
7802                 VectorNegate(plane.normal, plane.normal);
7803                 plane.dist *= -1;
7804                 PlaneClassify(&plane);
7805         }
7806
7807
7808         // find a matching plane if there is one
7809         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7810                 if(p->camera_entity == t->camera_entity)
7811                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
7812                                 break;
7813         if (planeindex >= r_waterstate.maxwaterplanes)
7814                 return; // nothing we can do, out of planes
7815
7816         // if this triangle does not fit any known plane rendered this frame, add one
7817         if (planeindex >= r_waterstate.numwaterplanes)
7818         {
7819                 // store the new plane
7820                 r_waterstate.numwaterplanes++;
7821                 p->plane = plane;
7822                 // clear materialflags and pvs
7823                 p->materialflags = 0;
7824                 p->pvsvalid = false;
7825                 p->camera_entity = t->camera_entity;
7826                 VectorCopy(surface->mins, p->mins);
7827                 VectorCopy(surface->maxs, p->maxs);
7828         }
7829         else
7830         {
7831                 // merge mins/maxs
7832                 p->mins[0] = min(p->mins[0], surface->mins[0]);
7833                 p->mins[1] = min(p->mins[1], surface->mins[1]);
7834                 p->mins[2] = min(p->mins[2], surface->mins[2]);
7835                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
7836                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
7837                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
7838         }
7839         // merge this surface's materialflags into the waterplane
7840         p->materialflags |= t->currentmaterialflags;
7841         if(!(p->materialflags & MATERIALFLAG_CAMERA))
7842         {
7843                 // merge this surface's PVS into the waterplane
7844                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7845                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7846                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7847                 {
7848                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7849                         p->pvsvalid = true;
7850                 }
7851         }
7852 }
7853
7854 static void R_Water_ProcessPlanes(void)
7855 {
7856         int myscissor[4];
7857         r_refdef_view_t originalview;
7858         r_refdef_view_t myview;
7859         int planeindex;
7860         r_waterstate_waterplane_t *p;
7861         vec3_t visorigin;
7862
7863         originalview = r_refdef.view;
7864
7865         // make sure enough textures are allocated
7866         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7867         {
7868                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7869                 {
7870                         if (!p->texture_refraction)
7871                                 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, -1, NULL);
7872                         if (!p->texture_refraction)
7873                                 goto error;
7874                 }
7875                 else if (p->materialflags & MATERIALFLAG_CAMERA)
7876                 {
7877                         if (!p->texture_camera)
7878                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR, -1, NULL);
7879                         if (!p->texture_camera)
7880                                 goto error;
7881                 }
7882
7883                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7884                 {
7885                         if (!p->texture_reflection)
7886                                 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, -1, NULL);
7887                         if (!p->texture_reflection)
7888                                 goto error;
7889                 }
7890         }
7891
7892         // render views
7893         r_refdef.view = originalview;
7894         r_refdef.view.showdebug = false;
7895         r_refdef.view.width = r_waterstate.waterwidth;
7896         r_refdef.view.height = r_waterstate.waterheight;
7897         r_refdef.view.useclipplane = true;
7898         myview = r_refdef.view;
7899         r_waterstate.renderingscene = true;
7900         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7901         {
7902                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7903                 {
7904                         r_refdef.view = myview;
7905                         if(r_water_scissormode.integer)
7906                         {
7907                                 R_SetupView(true);
7908                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
7909                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
7910                         }
7911
7912                         // render reflected scene and copy into texture
7913                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7914                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7915                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7916                         r_refdef.view.clipplane = p->plane;
7917
7918                         // reverse the cullface settings for this render
7919                         r_refdef.view.cullface_front = GL_FRONT;
7920                         r_refdef.view.cullface_back = GL_BACK;
7921                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7922                         {
7923                                 r_refdef.view.usecustompvs = true;
7924                                 if (p->pvsvalid)
7925                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7926                                 else
7927                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7928                         }
7929
7930                         R_ResetViewRendering3D();
7931                         R_ClearScreen(r_refdef.fogenabled);
7932                         if(r_water_scissormode.integer & 2)
7933                                 R_View_UpdateWithScissor(myscissor);
7934                         else
7935                                 R_View_Update();
7936                         if(r_water_scissormode.integer & 1)
7937                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
7938                         R_RenderScene();
7939
7940                         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);
7941                 }
7942
7943                 // render the normal view scene and copy into texture
7944                 // (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)
7945                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7946                 {
7947                         r_refdef.view = myview;
7948                         if(r_water_scissormode.integer)
7949                         {
7950                                 R_SetupView(true);
7951                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
7952                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
7953                         }
7954
7955                         r_waterstate.renderingrefraction = true;
7956
7957                         r_refdef.view.clipplane = p->plane;
7958                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7959                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7960
7961                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
7962                         {
7963                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
7964                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
7965                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
7966                                 R_RenderView_UpdateViewVectors();
7967                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
7968                                 {
7969                                         r_refdef.view.usecustompvs = true;
7970                                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
7971                                 }
7972                         }
7973
7974                         PlaneClassify(&r_refdef.view.clipplane);
7975
7976                         R_ResetViewRendering3D();
7977                         R_ClearScreen(r_refdef.fogenabled);
7978                         if(r_water_scissormode.integer & 2)
7979                                 R_View_UpdateWithScissor(myscissor);
7980                         else
7981                                 R_View_Update();
7982                         if(r_water_scissormode.integer & 1)
7983                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
7984                         R_RenderScene();
7985
7986                         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);
7987                         r_waterstate.renderingrefraction = false;
7988                 }
7989                 else if (p->materialflags & MATERIALFLAG_CAMERA)
7990                 {
7991                         r_refdef.view = myview;
7992
7993                         r_refdef.view.clipplane = p->plane;
7994                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7995                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7996
7997                         r_refdef.view.width = r_waterstate.camerawidth;
7998                         r_refdef.view.height = r_waterstate.cameraheight;
7999                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8000                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8001
8002                         if(p->camera_entity)
8003                         {
8004                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8005                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8006                         }
8007
8008                         // note: all of the view is used for displaying... so
8009                         // there is no use in scissoring
8010
8011                         // reverse the cullface settings for this render
8012                         r_refdef.view.cullface_front = GL_FRONT;
8013                         r_refdef.view.cullface_back = GL_BACK;
8014                         // also reverse the view matrix
8015                         Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, 1, -1); // this serves to invert texcoords in the result, as the copied texture is mapped the wrong way round
8016                         R_RenderView_UpdateViewVectors();
8017                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8018                         {
8019                                 r_refdef.view.usecustompvs = true;
8020                                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
8021                         }
8022                         
8023                         // camera needs no clipplane
8024                         r_refdef.view.useclipplane = false;
8025
8026                         PlaneClassify(&r_refdef.view.clipplane);
8027
8028                         R_ResetViewRendering3D();
8029                         R_ClearScreen(r_refdef.fogenabled);
8030                         R_View_Update();
8031                         R_RenderScene();
8032
8033                         R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8034                         r_waterstate.renderingrefraction = false;
8035                 }
8036
8037         }
8038         r_waterstate.renderingscene = false;
8039         r_refdef.view = originalview;
8040         R_ResetViewRendering3D();
8041         R_ClearScreen(r_refdef.fogenabled);
8042         R_View_Update();
8043         return;
8044 error:
8045         r_refdef.view = originalview;
8046         r_waterstate.renderingscene = false;
8047         Cvar_SetValueQuick(&r_water, 0);
8048         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8049         return;
8050 }
8051
8052 void R_Bloom_StartFrame(void)
8053 {
8054         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8055
8056         switch(vid.renderpath)
8057         {
8058         case RENDERPATH_GL20:
8059         case RENDERPATH_CGGL:
8060                 break;
8061         case RENDERPATH_GL13:
8062         case RENDERPATH_GL11:
8063                 return;
8064         }
8065
8066         // set bloomwidth and bloomheight to the bloom resolution that will be
8067         // used (often less than the screen resolution for faster rendering)
8068         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8069         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8070         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8071         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8072         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8073
8074         // calculate desired texture sizes
8075         if (vid.support.arb_texture_non_power_of_two)
8076         {
8077                 screentexturewidth = r_refdef.view.width;
8078                 screentextureheight = r_refdef.view.height;
8079                 bloomtexturewidth = r_bloomstate.bloomwidth;
8080                 bloomtextureheight = r_bloomstate.bloomheight;
8081         }
8082         else
8083         {
8084                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8085                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8086                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8087                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8088         }
8089
8090         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))
8091         {
8092                 Cvar_SetValueQuick(&r_hdr, 0);
8093                 Cvar_SetValueQuick(&r_bloom, 0);
8094                 Cvar_SetValueQuick(&r_motionblur, 0);
8095                 Cvar_SetValueQuick(&r_damageblur, 0);
8096         }
8097
8098         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)))
8099                 screentexturewidth = screentextureheight = 0;
8100         if (!r_hdr.integer && !r_bloom.integer)
8101                 bloomtexturewidth = bloomtextureheight = 0;
8102
8103         // allocate textures as needed
8104         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8105         {
8106                 if (r_bloomstate.texture_screen)
8107                         R_FreeTexture(r_bloomstate.texture_screen);
8108                 r_bloomstate.texture_screen = NULL;
8109                 r_bloomstate.screentexturewidth = screentexturewidth;
8110                 r_bloomstate.screentextureheight = screentextureheight;
8111                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8112                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
8113         }
8114         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8115         {
8116                 if (r_bloomstate.texture_bloom)
8117                         R_FreeTexture(r_bloomstate.texture_bloom);
8118                 r_bloomstate.texture_bloom = NULL;
8119                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8120                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8121                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8122                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8123         }
8124
8125         // when doing a reduced render (HDR) we want to use a smaller area
8126         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8127         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8128         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8129         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8130         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8131
8132         // set up a texcoord array for the full resolution screen image
8133         // (we have to keep this around to copy back during final render)
8134         r_bloomstate.screentexcoord2f[0] = 0;
8135         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8136         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8137         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8138         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8139         r_bloomstate.screentexcoord2f[5] = 0;
8140         r_bloomstate.screentexcoord2f[6] = 0;
8141         r_bloomstate.screentexcoord2f[7] = 0;
8142
8143         // set up a texcoord array for the reduced resolution bloom image
8144         // (which will be additive blended over the screen image)
8145         r_bloomstate.bloomtexcoord2f[0] = 0;
8146         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8147         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8148         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8149         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8150         r_bloomstate.bloomtexcoord2f[5] = 0;
8151         r_bloomstate.bloomtexcoord2f[6] = 0;
8152         r_bloomstate.bloomtexcoord2f[7] = 0;
8153
8154         if (r_hdr.integer || r_bloom.integer)
8155         {
8156                 r_bloomstate.enabled = true;
8157                 r_bloomstate.hdr = r_hdr.integer != 0;
8158         }
8159
8160         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);
8161 }
8162
8163 void R_Bloom_CopyBloomTexture(float colorscale)
8164 {
8165         r_refdef.stats.bloom++;
8166
8167         // scale down screen texture to the bloom texture size
8168         CHECKGLERROR
8169         R_SetViewport(&r_bloomstate.viewport);
8170         GL_BlendFunc(GL_ONE, GL_ZERO);
8171         GL_Color(colorscale, colorscale, colorscale, 1);
8172         // TODO: optimize with multitexture or GLSL
8173         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
8174         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8175         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8176         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8177
8178         // we now have a bloom image in the framebuffer
8179         // copy it into the bloom image texture for later processing
8180         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);
8181         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8182 }
8183
8184 void R_Bloom_CopyHDRTexture(void)
8185 {
8186         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);
8187         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8188 }
8189
8190 void R_Bloom_MakeTexture(void)
8191 {
8192         int x, range, dir;
8193         float xoffset, yoffset, r, brighten;
8194
8195         r_refdef.stats.bloom++;
8196
8197         R_ResetViewRendering2D();
8198         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8199         R_Mesh_ColorPointer(NULL, 0, 0);
8200
8201         // we have a bloom image in the framebuffer
8202         CHECKGLERROR
8203         R_SetViewport(&r_bloomstate.viewport);
8204
8205         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8206         {
8207                 x *= 2;
8208                 r = bound(0, r_bloom_colorexponent.value / x, 1);
8209                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8210                 GL_Color(r, r, r, 1);
8211                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8212                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
8213                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8214                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8215
8216                 // copy the vertically blurred bloom view to a texture
8217                 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);
8218                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8219         }
8220
8221         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8222         brighten = r_bloom_brighten.value;
8223         if (r_hdr.integer)
8224                 brighten *= r_hdr_range.value;
8225         brighten = sqrt(brighten);
8226         if(range >= 1)
8227                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8228         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8229         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
8230
8231         for (dir = 0;dir < 2;dir++)
8232         {
8233                 // blend on at multiple vertical offsets to achieve a vertical blur
8234                 // TODO: do offset blends using GLSL
8235                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8236                 GL_BlendFunc(GL_ONE, GL_ZERO);
8237                 for (x = -range;x <= range;x++)
8238                 {
8239                         if (!dir){xoffset = 0;yoffset = x;}
8240                         else {xoffset = x;yoffset = 0;}
8241                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
8242                         yoffset /= (float)r_bloomstate.bloomtextureheight;
8243                         // compute a texcoord array with the specified x and y offset
8244                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8245                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8246                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8247                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8248                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8249                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8250                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8251                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8252                         // this r value looks like a 'dot' particle, fading sharply to
8253                         // black at the edges
8254                         // (probably not realistic but looks good enough)
8255                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8256                         //r = brighten/(range*2+1);
8257                         r = brighten / (range * 2 + 1);
8258                         if(range >= 1)
8259                                 r *= (1 - x*x/(float)(range*range));
8260                         GL_Color(r, r, r, 1);
8261                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8262                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8263                         GL_BlendFunc(GL_ONE, GL_ONE);
8264                 }
8265
8266                 // copy the vertically blurred bloom view to a texture
8267                 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);
8268                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8269         }
8270
8271         // apply subtract last
8272         // (just like it would be in a GLSL shader)
8273         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
8274         {
8275                 GL_BlendFunc(GL_ONE, GL_ZERO);
8276                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8277                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
8278                 GL_Color(1, 1, 1, 1);
8279                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8280                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8281
8282                 GL_BlendFunc(GL_ONE, GL_ONE);
8283                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
8284                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8285                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
8286                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
8287                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8288                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8289                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
8290
8291                 // copy the darkened bloom view to a texture
8292                 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);
8293                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8294         }
8295 }
8296
8297 void R_HDR_RenderBloomTexture(void)
8298 {
8299         int oldwidth, oldheight;
8300         float oldcolorscale;
8301
8302         oldcolorscale = r_refdef.view.colorscale;
8303         oldwidth = r_refdef.view.width;
8304         oldheight = r_refdef.view.height;
8305         r_refdef.view.width = r_bloomstate.bloomwidth;
8306         r_refdef.view.height = r_bloomstate.bloomheight;
8307
8308         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
8309         // TODO: add exposure compensation features
8310         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8311
8312         r_refdef.view.showdebug = false;
8313         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8314
8315         R_ResetViewRendering3D();
8316
8317         R_ClearScreen(r_refdef.fogenabled);
8318         if (r_timereport_active)
8319                 R_TimeReport("HDRclear");
8320
8321         R_View_Update();
8322         if (r_timereport_active)
8323                 R_TimeReport("visibility");
8324
8325         // only do secondary renders with HDR if r_hdr is 2 or higher
8326         r_waterstate.numwaterplanes = 0;
8327         if (r_waterstate.enabled && r_hdr.integer >= 2)
8328                 R_RenderWaterPlanes();
8329
8330         r_refdef.view.showdebug = true;
8331         R_RenderScene();
8332         r_waterstate.numwaterplanes = 0;
8333
8334         R_ResetViewRendering2D();
8335
8336         R_Bloom_CopyHDRTexture();
8337         R_Bloom_MakeTexture();
8338
8339         // restore the view settings
8340         r_refdef.view.width = oldwidth;
8341         r_refdef.view.height = oldheight;
8342         r_refdef.view.colorscale = oldcolorscale;
8343
8344         R_ResetViewRendering3D();
8345
8346         R_ClearScreen(r_refdef.fogenabled);
8347         if (r_timereport_active)
8348                 R_TimeReport("viewclear");
8349 }
8350
8351 static void R_BlendView(void)
8352 {
8353         unsigned int permutation;
8354         float uservecs[4][4];
8355
8356         switch (vid.renderpath)
8357         {
8358         case RENDERPATH_GL20:
8359         case RENDERPATH_CGGL:
8360                 permutation =
8361                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8362                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8363                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8364                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8365                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8366
8367                 if (r_bloomstate.texture_screen)
8368                 {
8369                         // make sure the buffer is available
8370                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8371
8372                         R_ResetViewRendering2D();
8373                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8374                         R_Mesh_ColorPointer(NULL, 0, 0);
8375
8376                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8377                         {
8378                                 // declare variables
8379                                 float speed;
8380                                 static float avgspeed;
8381
8382                                 speed = VectorLength(cl.movement_velocity);
8383
8384                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8385                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8386
8387                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8388                                 speed = bound(0, speed, 1);
8389                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8390
8391                                 // calculate values into a standard alpha
8392                                 cl.motionbluralpha = 1 - exp(-
8393                                                 (
8394                                                  (r_motionblur.value * speed / 80)
8395                                                  +
8396                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8397                                                 )
8398                                                 /
8399                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
8400                                            );
8401
8402                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8403                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8404                                 // apply the blur
8405                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8406                                 {
8407                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8408                                         GL_Color(1, 1, 1, cl.motionbluralpha);
8409                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8410                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
8411                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8412                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8413                                 }
8414                         }
8415
8416                         // copy view into the screen texture
8417                         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);
8418                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8419                 }
8420                 else if (!r_bloomstate.texture_bloom)
8421                 {
8422                         // we may still have to do view tint...
8423                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8424                         {
8425                                 // apply a color tint to the whole view
8426                                 R_ResetViewRendering2D();
8427                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8428                                 R_Mesh_ColorPointer(NULL, 0, 0);
8429                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8430                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8431                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8432                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8433                         }
8434                         break; // no screen processing, no bloom, skip it
8435                 }
8436
8437                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8438                 {
8439                         // render simple bloom effect
8440                         // copy the screen and shrink it and darken it for the bloom process
8441                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8442                         // make the bloom texture
8443                         R_Bloom_MakeTexture();
8444                 }
8445
8446 #if _MSC_VER >= 1400
8447 #define sscanf sscanf_s
8448 #endif
8449                 memset(uservecs, 0, sizeof(uservecs));
8450                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8451                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8452                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
8453                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
8454
8455                 R_ResetViewRendering2D();
8456                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8457                 R_Mesh_ColorPointer(NULL, 0, 0);
8458                 GL_Color(1, 1, 1, 1);
8459                 GL_BlendFunc(GL_ONE, GL_ZERO);
8460                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
8461                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
8462
8463                 switch(vid.renderpath)
8464                 {
8465                 case RENDERPATH_GL20:
8466                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
8467                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
8468                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
8469                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
8470                         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]);
8471                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8472                         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]);
8473                         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]);
8474                         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]);
8475                         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]);
8476                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
8477                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8478                         break;
8479                 case RENDERPATH_CGGL:
8480 #ifdef SUPPORTCG
8481                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
8482                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
8483                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
8484                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
8485                         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
8486                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
8487                         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
8488                         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
8489                         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
8490                         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
8491                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
8492                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
8493 #endif
8494                         break;
8495                 default:
8496                         break;
8497                 }
8498                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8499                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8500                 break;
8501         case RENDERPATH_GL13:
8502         case RENDERPATH_GL11:
8503                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8504                 {
8505                         // apply a color tint to the whole view
8506                         R_ResetViewRendering2D();
8507                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8508                         R_Mesh_ColorPointer(NULL, 0, 0);
8509                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8510                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8511                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8512                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8513                 }
8514                 break;
8515         }
8516 }
8517
8518 matrix4x4_t r_waterscrollmatrix;
8519
8520 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
8521 {
8522         if (r_refdef.fog_density)
8523         {
8524                 r_refdef.fogcolor[0] = r_refdef.fog_red;
8525                 r_refdef.fogcolor[1] = r_refdef.fog_green;
8526                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
8527
8528                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
8529                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
8530                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
8531                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
8532
8533                 {
8534                         vec3_t fogvec;
8535                         VectorCopy(r_refdef.fogcolor, fogvec);
8536                         //   color.rgb *= ContrastBoost * SceneBrightness;
8537                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
8538                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
8539                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
8540                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
8541                 }
8542         }
8543 }
8544
8545 void R_UpdateVariables(void)
8546 {
8547         R_Textures_Frame();
8548
8549         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
8550
8551         r_refdef.farclip = r_farclip_base.value;
8552         if (r_refdef.scene.worldmodel)
8553                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
8554         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
8555
8556         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8557                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8558         r_refdef.polygonfactor = 0;
8559         r_refdef.polygonoffset = 0;
8560         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8561         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8562
8563         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8564         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8565         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
8566         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8567         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8568         if (FAKELIGHT_ENABLED)
8569         {
8570                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
8571         }
8572         if (r_showsurfaces.integer)
8573         {
8574                 r_refdef.scene.rtworld = false;
8575                 r_refdef.scene.rtworldshadows = false;
8576                 r_refdef.scene.rtdlight = false;
8577                 r_refdef.scene.rtdlightshadows = false;
8578                 r_refdef.lightmapintensity = 0;
8579         }
8580
8581         if (gamemode == GAME_NEHAHRA)
8582         {
8583                 if (gl_fogenable.integer)
8584                 {
8585                         r_refdef.oldgl_fogenable = true;
8586                         r_refdef.fog_density = gl_fogdensity.value;
8587                         r_refdef.fog_red = gl_fogred.value;
8588                         r_refdef.fog_green = gl_foggreen.value;
8589                         r_refdef.fog_blue = gl_fogblue.value;
8590                         r_refdef.fog_alpha = 1;
8591                         r_refdef.fog_start = 0;
8592                         r_refdef.fog_end = gl_skyclip.value;
8593                         r_refdef.fog_height = 1<<30;
8594                         r_refdef.fog_fadedepth = 128;
8595                 }
8596                 else if (r_refdef.oldgl_fogenable)
8597                 {
8598                         r_refdef.oldgl_fogenable = false;
8599                         r_refdef.fog_density = 0;
8600                         r_refdef.fog_red = 0;
8601                         r_refdef.fog_green = 0;
8602                         r_refdef.fog_blue = 0;
8603                         r_refdef.fog_alpha = 0;
8604                         r_refdef.fog_start = 0;
8605                         r_refdef.fog_end = 0;
8606                         r_refdef.fog_height = 1<<30;
8607                         r_refdef.fog_fadedepth = 128;
8608                 }
8609         }
8610
8611         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
8612         r_refdef.fog_start = max(0, r_refdef.fog_start);
8613         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
8614
8615         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
8616
8617         if (r_refdef.fog_density && r_drawfog.integer)
8618         {
8619                 r_refdef.fogenabled = true;
8620                 // this is the point where the fog reaches 0.9986 alpha, which we
8621                 // consider a good enough cutoff point for the texture
8622                 // (0.9986 * 256 == 255.6)
8623                 if (r_fog_exp2.integer)
8624                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
8625                 else
8626                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
8627                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
8628                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
8629                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
8630                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
8631                         R_BuildFogHeightTexture();
8632                 // fog color was already set
8633                 // update the fog texture
8634                 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)
8635                         R_BuildFogTexture();
8636                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
8637                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
8638         }
8639         else
8640                 r_refdef.fogenabled = false;
8641
8642         switch(vid.renderpath)
8643         {
8644         case RENDERPATH_GL20:
8645         case RENDERPATH_CGGL:
8646                 if(v_glslgamma.integer && !vid_gammatables_trivial)
8647                 {
8648                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
8649                         {
8650                                 // build GLSL gamma texture
8651 #define RAMPWIDTH 256
8652                                 unsigned short ramp[RAMPWIDTH * 3];
8653                                 unsigned char rampbgr[RAMPWIDTH][4];
8654                                 int i;
8655
8656                                 r_texture_gammaramps_serial = vid_gammatables_serial;
8657
8658                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
8659                                 for(i = 0; i < RAMPWIDTH; ++i)
8660                                 {
8661                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8662                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8663                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
8664                                         rampbgr[i][3] = 0;
8665                                 }
8666                                 if (r_texture_gammaramps)
8667                                 {
8668                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
8669                                 }
8670                                 else
8671                                 {
8672                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
8673                                 }
8674                         }
8675                 }
8676                 else
8677                 {
8678                         // remove GLSL gamma texture
8679                 }
8680                 break;
8681         case RENDERPATH_GL13:
8682         case RENDERPATH_GL11:
8683                 break;
8684         }
8685 }
8686
8687 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
8688 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
8689 /*
8690 ================
8691 R_SelectScene
8692 ================
8693 */
8694 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
8695         if( scenetype != r_currentscenetype ) {
8696                 // store the old scenetype
8697                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
8698                 r_currentscenetype = scenetype;
8699                 // move in the new scene
8700                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
8701         }
8702 }
8703
8704 /*
8705 ================
8706 R_GetScenePointer
8707 ================
8708 */
8709 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
8710 {
8711         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
8712         if( scenetype == r_currentscenetype ) {
8713                 return &r_refdef.scene;
8714         } else {
8715                 return &r_scenes_store[ scenetype ];
8716         }
8717 }
8718
8719 /*
8720 ================
8721 R_RenderView
8722 ================
8723 */
8724 void R_RenderView(void)
8725 {
8726         if (r_timereport_active)
8727                 R_TimeReport("start");
8728         r_textureframe++; // used only by R_GetCurrentTexture
8729         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8730
8731         if (!r_drawentities.integer)
8732                 r_refdef.scene.numentities = 0;
8733
8734         R_AnimCache_ClearCache();
8735         R_FrameData_NewFrame();
8736
8737         if (r_refdef.view.isoverlay)
8738         {
8739                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
8740                 GL_Clear( GL_DEPTH_BUFFER_BIT );
8741                 R_TimeReport("depthclear");
8742
8743                 r_refdef.view.showdebug = false;
8744
8745                 r_waterstate.enabled = false;
8746                 r_waterstate.numwaterplanes = 0;
8747
8748                 R_RenderScene();
8749
8750                 CHECKGLERROR
8751                 return;
8752         }
8753
8754         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
8755                 return; //Host_Error ("R_RenderView: NULL worldmodel");
8756
8757         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
8758
8759         R_RenderView_UpdateViewVectors();
8760
8761         R_Shadow_UpdateWorldLightSelection();
8762
8763         R_Bloom_StartFrame();
8764         R_Water_StartFrame();
8765
8766         CHECKGLERROR
8767         if (r_timereport_active)
8768                 R_TimeReport("viewsetup");
8769
8770         R_ResetViewRendering3D();
8771
8772         if (r_refdef.view.clear || r_refdef.fogenabled)
8773         {
8774                 R_ClearScreen(r_refdef.fogenabled);
8775                 if (r_timereport_active)
8776                         R_TimeReport("viewclear");
8777         }
8778         r_refdef.view.clear = true;
8779
8780         // this produces a bloom texture to be used in R_BlendView() later
8781         if (r_hdr.integer && r_bloomstate.bloomwidth)
8782         {
8783                 R_HDR_RenderBloomTexture();
8784                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
8785                 r_textureframe++; // used only by R_GetCurrentTexture
8786         }
8787
8788         r_refdef.view.showdebug = true;
8789
8790         R_View_Update();
8791         if (r_timereport_active)
8792                 R_TimeReport("visibility");
8793
8794         r_waterstate.numwaterplanes = 0;
8795         if (r_waterstate.enabled)
8796                 R_RenderWaterPlanes();
8797
8798         R_RenderScene();
8799         r_waterstate.numwaterplanes = 0;
8800
8801         R_BlendView();
8802         if (r_timereport_active)
8803                 R_TimeReport("blendview");
8804
8805         GL_Scissor(0, 0, vid.width, vid.height);
8806         GL_ScissorTest(false);
8807
8808         CHECKGLERROR
8809 }
8810
8811 void R_RenderWaterPlanes(void)
8812 {
8813         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
8814         {
8815                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
8816                 if (r_timereport_active)
8817                         R_TimeReport("waterworld");
8818         }
8819
8820         // don't let sound skip if going slow
8821         if (r_refdef.scene.extraupdate)
8822                 S_ExtraUpdate ();
8823
8824         R_DrawModelsAddWaterPlanes();
8825         if (r_timereport_active)
8826                 R_TimeReport("watermodels");
8827
8828         if (r_waterstate.numwaterplanes)
8829         {
8830                 R_Water_ProcessPlanes();
8831                 if (r_timereport_active)
8832                         R_TimeReport("waterscenes");
8833         }
8834 }
8835
8836 extern void R_DrawLightningBeams (void);
8837 extern void VM_CL_AddPolygonsToMeshQueue (void);
8838 extern void R_DrawPortals (void);
8839 extern cvar_t cl_locs_show;
8840 static void R_DrawLocs(void);
8841 static void R_DrawEntityBBoxes(void);
8842 static void R_DrawModelDecals(void);
8843 extern void R_DrawModelShadows(void);
8844 extern void R_DrawModelShadowMaps(void);
8845 extern cvar_t cl_decals_newsystem;
8846 extern qboolean r_shadow_usingdeferredprepass;
8847 void R_RenderScene(void)
8848 {
8849         qboolean shadowmapping = false;
8850
8851         if (r_timereport_active)
8852                 R_TimeReport("beginscene");
8853
8854         r_refdef.stats.renders++;
8855
8856         R_UpdateFogColor();
8857
8858         // don't let sound skip if going slow
8859         if (r_refdef.scene.extraupdate)
8860                 S_ExtraUpdate ();
8861
8862         R_MeshQueue_BeginScene();
8863
8864         R_SkyStartFrame();
8865
8866         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);
8867
8868         if (r_timereport_active)
8869                 R_TimeReport("skystartframe");
8870
8871         if (cl.csqc_vidvars.drawworld)
8872         {
8873                 // don't let sound skip if going slow
8874                 if (r_refdef.scene.extraupdate)
8875                         S_ExtraUpdate ();
8876
8877                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
8878                 {
8879                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
8880                         if (r_timereport_active)
8881                                 R_TimeReport("worldsky");
8882                 }
8883
8884                 if (R_DrawBrushModelsSky() && r_timereport_active)
8885                         R_TimeReport("bmodelsky");
8886
8887                 if (skyrendermasked && skyrenderlater)
8888                 {
8889                         // we have to force off the water clipping plane while rendering sky
8890                         R_SetupView(false);
8891                         R_Sky();
8892                         R_SetupView(true);
8893                         if (r_timereport_active)
8894                                 R_TimeReport("sky");
8895                 }
8896         }
8897
8898         R_AnimCache_CacheVisibleEntities();
8899         if (r_timereport_active)
8900                 R_TimeReport("animation");
8901
8902         R_Shadow_PrepareLights();
8903         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
8904                 R_Shadow_PrepareModelShadows();
8905         if (r_timereport_active)
8906                 R_TimeReport("preparelights");
8907
8908         if (R_Shadow_ShadowMappingEnabled())
8909                 shadowmapping = true;
8910
8911         if (r_shadow_usingdeferredprepass)
8912                 R_Shadow_DrawPrepass();
8913
8914         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
8915         {
8916                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
8917                 if (r_timereport_active)
8918                         R_TimeReport("worlddepth");
8919         }
8920         if (r_depthfirst.integer >= 2)
8921         {
8922                 R_DrawModelsDepth();
8923                 if (r_timereport_active)
8924                         R_TimeReport("modeldepth");
8925         }
8926
8927         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
8928         {
8929                 R_DrawModelShadowMaps();
8930                 R_ResetViewRendering3D();
8931                 // don't let sound skip if going slow
8932                 if (r_refdef.scene.extraupdate)
8933                         S_ExtraUpdate ();
8934         }
8935
8936         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
8937         {
8938                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
8939                 if (r_timereport_active)
8940                         R_TimeReport("world");
8941         }
8942
8943         // don't let sound skip if going slow
8944         if (r_refdef.scene.extraupdate)
8945                 S_ExtraUpdate ();
8946
8947         R_DrawModels();
8948         if (r_timereport_active)
8949                 R_TimeReport("models");
8950
8951         // don't let sound skip if going slow
8952         if (r_refdef.scene.extraupdate)
8953                 S_ExtraUpdate ();
8954
8955         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8956         {
8957                 R_DrawModelShadows();
8958                 R_ResetViewRendering3D();
8959                 // don't let sound skip if going slow
8960                 if (r_refdef.scene.extraupdate)
8961                         S_ExtraUpdate ();
8962         }
8963
8964         if (!r_shadow_usingdeferredprepass)
8965         {
8966                 R_Shadow_DrawLights();
8967                 if (r_timereport_active)
8968                         R_TimeReport("rtlights");
8969         }
8970
8971         // don't let sound skip if going slow
8972         if (r_refdef.scene.extraupdate)
8973                 S_ExtraUpdate ();
8974
8975         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8976         {
8977                 R_DrawModelShadows();
8978                 R_ResetViewRendering3D();
8979                 // don't let sound skip if going slow
8980                 if (r_refdef.scene.extraupdate)
8981                         S_ExtraUpdate ();
8982         }
8983
8984         if (cl.csqc_vidvars.drawworld)
8985         {
8986                 if (cl_decals_newsystem.integer)
8987                 {
8988                         R_DrawModelDecals();
8989                         if (r_timereport_active)
8990                                 R_TimeReport("modeldecals");
8991                 }
8992                 else
8993                 {
8994                         R_DrawDecals();
8995                         if (r_timereport_active)
8996                                 R_TimeReport("decals");
8997                 }
8998
8999                 R_DrawParticles();
9000                 if (r_timereport_active)
9001                         R_TimeReport("particles");
9002
9003                 R_DrawExplosions();
9004                 if (r_timereport_active)
9005                         R_TimeReport("explosions");
9006
9007                 R_DrawLightningBeams();
9008                 if (r_timereport_active)
9009                         R_TimeReport("lightning");
9010         }
9011
9012         VM_CL_AddPolygonsToMeshQueue();
9013
9014         if (r_refdef.view.showdebug)
9015         {
9016                 if (cl_locs_show.integer)
9017                 {
9018                         R_DrawLocs();
9019                         if (r_timereport_active)
9020                                 R_TimeReport("showlocs");
9021                 }
9022
9023                 if (r_drawportals.integer)
9024                 {
9025                         R_DrawPortals();
9026                         if (r_timereport_active)
9027                                 R_TimeReport("portals");
9028                 }
9029
9030                 if (r_showbboxes.value > 0)
9031                 {
9032                         R_DrawEntityBBoxes();
9033                         if (r_timereport_active)
9034                                 R_TimeReport("bboxes");
9035                 }
9036         }
9037
9038         R_MeshQueue_RenderTransparent();
9039         if (r_timereport_active)
9040                 R_TimeReport("drawtrans");
9041
9042         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))
9043         {
9044                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9045                 if (r_timereport_active)
9046                         R_TimeReport("worlddebug");
9047                 R_DrawModelsDebug();
9048                 if (r_timereport_active)
9049                         R_TimeReport("modeldebug");
9050         }
9051
9052         if (cl.csqc_vidvars.drawworld)
9053         {
9054                 R_Shadow_DrawCoronas();
9055                 if (r_timereport_active)
9056                         R_TimeReport("coronas");
9057         }
9058
9059 #if 0
9060         {
9061                 GL_DepthTest(false);
9062                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9063                 GL_Color(1, 1, 1, 1);
9064                 qglBegin(GL_POLYGON);
9065                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9066                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9067                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9068                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9069                 qglEnd();
9070                 qglBegin(GL_POLYGON);
9071                 qglVertex3f(r_refdef.view.frustumcorner[0][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[0][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[0][2] + 1000 * r_refdef.view.forward[2]);
9072                 qglVertex3f(r_refdef.view.frustumcorner[1][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[1][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[1][2] + 1000 * r_refdef.view.forward[2]);
9073                 qglVertex3f(r_refdef.view.frustumcorner[3][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[3][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[3][2] + 1000 * r_refdef.view.forward[2]);
9074                 qglVertex3f(r_refdef.view.frustumcorner[2][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[2][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[2][2] + 1000 * r_refdef.view.forward[2]);
9075                 qglEnd();
9076                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9077         }
9078 #endif
9079
9080         // don't let sound skip if going slow
9081         if (r_refdef.scene.extraupdate)
9082                 S_ExtraUpdate ();
9083
9084         R_ResetViewRendering2D();
9085 }
9086
9087 static const unsigned short bboxelements[36] =
9088 {
9089         5, 1, 3, 5, 3, 7,
9090         6, 2, 0, 6, 0, 4,
9091         7, 3, 2, 7, 2, 6,
9092         4, 0, 1, 4, 1, 5,
9093         4, 5, 7, 4, 7, 6,
9094         1, 0, 2, 1, 2, 3,
9095 };
9096
9097 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9098 {
9099         int i;
9100         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9101
9102         RSurf_ActiveWorldEntity();
9103
9104         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9105         GL_DepthMask(false);
9106         GL_DepthRange(0, 1);
9107         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9108         R_Mesh_ResetTextureState();
9109
9110         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9111         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9112         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9113         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9114         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9115         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9116         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9117         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9118         R_FillColors(color4f, 8, cr, cg, cb, ca);
9119         if (r_refdef.fogenabled)
9120         {
9121                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9122                 {
9123                         f1 = RSurf_FogVertex(v);
9124                         f2 = 1 - f1;
9125                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9126                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9127                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9128                 }
9129         }
9130         R_Mesh_VertexPointer(vertex3f, 0, 0);
9131         R_Mesh_ColorPointer(color4f, 0, 0);
9132         R_Mesh_ResetTextureState();
9133         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9134         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
9135 }
9136
9137 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9138 {
9139         int i;
9140         float color[4];
9141         prvm_edict_t *edict;
9142         prvm_prog_t *prog_save = prog;
9143
9144         // this function draws bounding boxes of server entities
9145         if (!sv.active)
9146                 return;
9147
9148         GL_CullFace(GL_NONE);
9149         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9150
9151         prog = 0;
9152         SV_VM_Begin();
9153         for (i = 0;i < numsurfaces;i++)
9154         {
9155                 edict = PRVM_EDICT_NUM(surfacelist[i]);
9156                 switch ((int)edict->fields.server->solid)
9157                 {
9158                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
9159                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
9160                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
9161                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9162                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
9163                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
9164                 }
9165                 color[3] *= r_showbboxes.value;
9166                 color[3] = bound(0, color[3], 1);
9167                 GL_DepthTest(!r_showdisabledepthtest.integer);
9168                 GL_CullFace(r_refdef.view.cullface_front);
9169                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9170         }
9171         SV_VM_End();
9172         prog = prog_save;
9173 }
9174
9175 static void R_DrawEntityBBoxes(void)
9176 {
9177         int i;
9178         prvm_edict_t *edict;
9179         vec3_t center;
9180         prvm_prog_t *prog_save = prog;
9181
9182         // this function draws bounding boxes of server entities
9183         if (!sv.active)
9184                 return;
9185
9186         prog = 0;
9187         SV_VM_Begin();
9188         for (i = 0;i < prog->num_edicts;i++)
9189         {
9190                 edict = PRVM_EDICT_NUM(i);
9191                 if (edict->priv.server->free)
9192                         continue;
9193                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9194                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9195                         continue;
9196                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9197                         continue;
9198                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9199                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9200         }
9201         SV_VM_End();
9202         prog = prog_save;
9203 }
9204
9205 static const int nomodelelement3i[24] =
9206 {
9207         5, 2, 0,
9208         5, 1, 2,
9209         5, 0, 3,
9210         5, 3, 1,
9211         0, 2, 4,
9212         2, 1, 4,
9213         3, 0, 4,
9214         1, 3, 4
9215 };
9216
9217 static const unsigned short nomodelelement3s[24] =
9218 {
9219         5, 2, 0,
9220         5, 1, 2,
9221         5, 0, 3,
9222         5, 3, 1,
9223         0, 2, 4,
9224         2, 1, 4,
9225         3, 0, 4,
9226         1, 3, 4
9227 };
9228
9229 static const float nomodelvertex3f[6*3] =
9230 {
9231         -16,   0,   0,
9232          16,   0,   0,
9233           0, -16,   0,
9234           0,  16,   0,
9235           0,   0, -16,
9236           0,   0,  16
9237 };
9238
9239 static const float nomodelcolor4f[6*4] =
9240 {
9241         0.0f, 0.0f, 0.5f, 1.0f,
9242         0.0f, 0.0f, 0.5f, 1.0f,
9243         0.0f, 0.5f, 0.0f, 1.0f,
9244         0.0f, 0.5f, 0.0f, 1.0f,
9245         0.5f, 0.0f, 0.0f, 1.0f,
9246         0.5f, 0.0f, 0.0f, 1.0f
9247 };
9248
9249 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9250 {
9251         int i;
9252         float f1, f2, *c;
9253         float color4f[6*4];
9254
9255         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);
9256
9257         // this is only called once per entity so numsurfaces is always 1, and
9258         // surfacelist is always {0}, so this code does not handle batches
9259
9260         if (rsurface.ent_flags & RENDER_ADDITIVE)
9261         {
9262                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9263                 GL_DepthMask(false);
9264         }
9265         else if (rsurface.colormod[3] < 1)
9266         {
9267                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9268                 GL_DepthMask(false);
9269         }
9270         else
9271         {
9272                 GL_BlendFunc(GL_ONE, GL_ZERO);
9273                 GL_DepthMask(true);
9274         }
9275         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9276         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9277         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9278         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9279         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9280         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9281         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9282         R_Mesh_ColorPointer(color4f, 0, 0);
9283         for (i = 0, c = color4f;i < 6;i++, c += 4)
9284         {
9285                 c[0] *= rsurface.colormod[0];
9286                 c[1] *= rsurface.colormod[1];
9287                 c[2] *= rsurface.colormod[2];
9288                 c[3] *= rsurface.colormod[3];
9289         }
9290         if (r_refdef.fogenabled)
9291         {
9292                 for (i = 0, c = color4f;i < 6;i++, c += 4)
9293                 {
9294                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
9295                         f2 = 1 - f1;
9296                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9297                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9298                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9299                 }
9300         }
9301         R_Mesh_ResetTextureState();
9302         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
9303 }
9304
9305 void R_DrawNoModel(entity_render_t *ent)
9306 {
9307         vec3_t org;
9308         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9309         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9310                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9311         else
9312                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9313 }
9314
9315 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9316 {
9317         vec3_t right1, right2, diff, normal;
9318
9319         VectorSubtract (org2, org1, normal);
9320
9321         // calculate 'right' vector for start
9322         VectorSubtract (r_refdef.view.origin, org1, diff);
9323         CrossProduct (normal, diff, right1);
9324         VectorNormalize (right1);
9325
9326         // calculate 'right' vector for end
9327         VectorSubtract (r_refdef.view.origin, org2, diff);
9328         CrossProduct (normal, diff, right2);
9329         VectorNormalize (right2);
9330
9331         vert[ 0] = org1[0] + width * right1[0];
9332         vert[ 1] = org1[1] + width * right1[1];
9333         vert[ 2] = org1[2] + width * right1[2];
9334         vert[ 3] = org1[0] - width * right1[0];
9335         vert[ 4] = org1[1] - width * right1[1];
9336         vert[ 5] = org1[2] - width * right1[2];
9337         vert[ 6] = org2[0] - width * right2[0];
9338         vert[ 7] = org2[1] - width * right2[1];
9339         vert[ 8] = org2[2] - width * right2[2];
9340         vert[ 9] = org2[0] + width * right2[0];
9341         vert[10] = org2[1] + width * right2[1];
9342         vert[11] = org2[2] + width * right2[2];
9343 }
9344
9345 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)
9346 {
9347         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9348         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9349         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9350         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9351         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9352         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9353         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9354         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9355         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9356         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9357         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9358         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9359 }
9360
9361 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9362 {
9363         int i;
9364         float *vertex3f;
9365         float v[3];
9366         VectorSet(v, x, y, z);
9367         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9368                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9369                         break;
9370         if (i == mesh->numvertices)
9371         {
9372                 if (mesh->numvertices < mesh->maxvertices)
9373                 {
9374                         VectorCopy(v, vertex3f);
9375                         mesh->numvertices++;
9376                 }
9377                 return mesh->numvertices;
9378         }
9379         else
9380                 return i;
9381 }
9382
9383 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9384 {
9385         int i;
9386         int *e, element[3];
9387         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9388         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9389         e = mesh->element3i + mesh->numtriangles * 3;
9390         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9391         {
9392                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9393                 if (mesh->numtriangles < mesh->maxtriangles)
9394                 {
9395                         *e++ = element[0];
9396                         *e++ = element[1];
9397                         *e++ = element[2];
9398                         mesh->numtriangles++;
9399                 }
9400                 element[1] = element[2];
9401         }
9402 }
9403
9404 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9405 {
9406         int i;
9407         int *e, element[3];
9408         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9409         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9410         e = mesh->element3i + mesh->numtriangles * 3;
9411         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9412         {
9413                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9414                 if (mesh->numtriangles < mesh->maxtriangles)
9415                 {
9416                         *e++ = element[0];
9417                         *e++ = element[1];
9418                         *e++ = element[2];
9419                         mesh->numtriangles++;
9420                 }
9421                 element[1] = element[2];
9422         }
9423 }
9424
9425 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9426 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9427 {
9428         int planenum, planenum2;
9429         int w;
9430         int tempnumpoints;
9431         mplane_t *plane, *plane2;
9432         double maxdist;
9433         double temppoints[2][256*3];
9434         // figure out how large a bounding box we need to properly compute this brush
9435         maxdist = 0;
9436         for (w = 0;w < numplanes;w++)
9437                 maxdist = max(maxdist, fabs(planes[w].dist));
9438         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9439         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9440         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9441         {
9442                 w = 0;
9443                 tempnumpoints = 4;
9444                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9445                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9446                 {
9447                         if (planenum2 == planenum)
9448                                 continue;
9449                         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);
9450                         w = !w;
9451                 }
9452                 if (tempnumpoints < 3)
9453                         continue;
9454                 // generate elements forming a triangle fan for this polygon
9455                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
9456         }
9457 }
9458
9459 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)
9460 {
9461         texturelayer_t *layer;
9462         layer = t->currentlayers + t->currentnumlayers++;
9463         layer->type = type;
9464         layer->depthmask = depthmask;
9465         layer->blendfunc1 = blendfunc1;
9466         layer->blendfunc2 = blendfunc2;
9467         layer->texture = texture;
9468         layer->texmatrix = *matrix;
9469         layer->color[0] = r;
9470         layer->color[1] = g;
9471         layer->color[2] = b;
9472         layer->color[3] = a;
9473 }
9474
9475 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
9476 {
9477         if(parms[0] == 0 && parms[1] == 0)
9478                 return false;
9479         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9480                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
9481                         return false;
9482         return true;
9483 }
9484
9485 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
9486 {
9487         double index, f;
9488         index = parms[2] + r_refdef.scene.time * parms[3];
9489         index -= floor(index);
9490         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
9491         {
9492         default:
9493         case Q3WAVEFUNC_NONE:
9494         case Q3WAVEFUNC_NOISE:
9495         case Q3WAVEFUNC_COUNT:
9496                 f = 0;
9497                 break;
9498         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
9499         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
9500         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
9501         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
9502         case Q3WAVEFUNC_TRIANGLE:
9503                 index *= 4;
9504                 f = index - floor(index);
9505                 if (index < 1)
9506                         f = f;
9507                 else if (index < 2)
9508                         f = 1 - f;
9509                 else if (index < 3)
9510                         f = -f;
9511                 else
9512                         f = -(1 - f);
9513                 break;
9514         }
9515         f = parms[0] + parms[1] * f;
9516         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9517                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
9518         return (float) f;
9519 }
9520
9521 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
9522 {
9523         int w, h, idx;
9524         float f;
9525         float tcmat[12];
9526         matrix4x4_t matrix, temp;
9527         switch(tcmod->tcmod)
9528         {
9529                 case Q3TCMOD_COUNT:
9530                 case Q3TCMOD_NONE:
9531                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9532                                 matrix = r_waterscrollmatrix;
9533                         else
9534                                 matrix = identitymatrix;
9535                         break;
9536                 case Q3TCMOD_ENTITYTRANSLATE:
9537                         // this is used in Q3 to allow the gamecode to control texcoord
9538                         // scrolling on the entity, which is not supported in darkplaces yet.
9539                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
9540                         break;
9541                 case Q3TCMOD_ROTATE:
9542                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
9543                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
9544                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
9545                         break;
9546                 case Q3TCMOD_SCALE:
9547                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
9548                         break;
9549                 case Q3TCMOD_SCROLL:
9550                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
9551                         break;
9552                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
9553                         w = (int) tcmod->parms[0];
9554                         h = (int) tcmod->parms[1];
9555                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
9556                         f = f - floor(f);
9557                         idx = (int) floor(f * w * h);
9558                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
9559                         break;
9560                 case Q3TCMOD_STRETCH:
9561                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
9562                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
9563                         break;
9564                 case Q3TCMOD_TRANSFORM:
9565                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
9566                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
9567                         VectorSet(tcmat +  6, 0                   , 0                , 1);
9568                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
9569                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
9570                         break;
9571                 case Q3TCMOD_TURBULENT:
9572                         // this is handled in the RSurf_PrepareVertices function
9573                         matrix = identitymatrix;
9574                         break;
9575         }
9576         temp = *texmatrix;
9577         Matrix4x4_Concat(texmatrix, &matrix, &temp);
9578 }
9579
9580 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
9581 {
9582         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
9583         char name[MAX_QPATH];
9584         skinframe_t *skinframe;
9585         unsigned char pixels[296*194];
9586         strlcpy(cache->name, skinname, sizeof(cache->name));
9587         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
9588         if (developer_loading.integer)
9589                 Con_Printf("loading %s\n", name);
9590         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
9591         if (!skinframe || !skinframe->base)
9592         {
9593                 unsigned char *f;
9594                 fs_offset_t filesize;
9595                 skinframe = NULL;
9596                 f = FS_LoadFile(name, tempmempool, true, &filesize);
9597                 if (f)
9598                 {
9599                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
9600                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
9601                         Mem_Free(f);
9602                 }
9603         }
9604         cache->skinframe = skinframe;
9605 }
9606
9607 texture_t *R_GetCurrentTexture(texture_t *t)
9608 {
9609         int i;
9610         const entity_render_t *ent = rsurface.entity;
9611         dp_model_t *model = ent->model;
9612         q3shaderinfo_layer_tcmod_t *tcmod;
9613
9614         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
9615                 return t->currentframe;
9616         t->update_lastrenderframe = r_textureframe;
9617         t->update_lastrenderentity = (void *)ent;
9618
9619         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
9620                 t->camera_entity = ent->entitynumber;
9621         else
9622                 t->camera_entity = 0;
9623
9624         // switch to an alternate material if this is a q1bsp animated material
9625         {
9626                 texture_t *texture = t;
9627                 int s = rsurface.ent_skinnum;
9628                 if ((unsigned int)s >= (unsigned int)model->numskins)
9629                         s = 0;
9630                 if (model->skinscenes)
9631                 {
9632                         if (model->skinscenes[s].framecount > 1)
9633                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
9634                         else
9635                                 s = model->skinscenes[s].firstframe;
9636                 }
9637                 if (s > 0)
9638                         t = t + s * model->num_surfaces;
9639                 if (t->animated)
9640                 {
9641                         // use an alternate animation if the entity's frame is not 0,
9642                         // and only if the texture has an alternate animation
9643                         if (rsurface.ent_alttextures && t->anim_total[1])
9644                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
9645                         else
9646                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
9647                 }
9648                 texture->currentframe = t;
9649         }
9650
9651         // update currentskinframe to be a qw skin or animation frame
9652         if (rsurface.ent_qwskin >= 0)
9653         {
9654                 i = rsurface.ent_qwskin;
9655                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
9656                 {
9657                         r_qwskincache_size = cl.maxclients;
9658                         if (r_qwskincache)
9659                                 Mem_Free(r_qwskincache);
9660                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
9661                 }
9662                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
9663                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
9664                 t->currentskinframe = r_qwskincache[i].skinframe;
9665                 if (t->currentskinframe == NULL)
9666                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9667         }
9668         else if (t->numskinframes >= 2)
9669                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9670         if (t->backgroundnumskinframes >= 2)
9671                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
9672
9673         t->currentmaterialflags = t->basematerialflags;
9674         t->currentalpha = rsurface.colormod[3];
9675         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
9676                 t->currentalpha *= r_wateralpha.value;
9677         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
9678                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
9679         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
9680                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
9681         if (!(rsurface.ent_flags & RENDER_LIGHT))
9682                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
9683         else if (FAKELIGHT_ENABLED)
9684         {
9685                         // no modellight if using fakelight for the map
9686         }
9687         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
9688         {
9689                 // pick a model lighting mode
9690                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
9691                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
9692                 else
9693                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
9694         }
9695         if (rsurface.ent_flags & RENDER_ADDITIVE)
9696                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9697         else if (t->currentalpha < 1)
9698                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9699         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
9700                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
9701         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
9702                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
9703         if (t->backgroundnumskinframes)
9704                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
9705         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
9706         {
9707                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
9708                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
9709         }
9710         else
9711                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
9712         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
9713                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
9714
9715         // there is no tcmod
9716         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9717         {
9718                 t->currenttexmatrix = r_waterscrollmatrix;
9719                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
9720         }
9721         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
9722         {
9723                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
9724                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
9725         }
9726
9727         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9728                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
9729         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9730                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
9731
9732         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
9733         if (t->currentskinframe->qpixels)
9734                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
9735         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
9736         if (!t->basetexture)
9737                 t->basetexture = r_texture_notexture;
9738         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
9739         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
9740         t->nmaptexture = t->currentskinframe->nmap;
9741         if (!t->nmaptexture)
9742                 t->nmaptexture = r_texture_blanknormalmap;
9743         t->glosstexture = r_texture_black;
9744         t->glowtexture = t->currentskinframe->glow;
9745         t->fogtexture = t->currentskinframe->fog;
9746         t->reflectmasktexture = t->currentskinframe->reflect;
9747         if (t->backgroundnumskinframes)
9748         {
9749                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
9750                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
9751                 t->backgroundglosstexture = r_texture_black;
9752                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
9753                 if (!t->backgroundnmaptexture)
9754                         t->backgroundnmaptexture = r_texture_blanknormalmap;
9755         }
9756         else
9757         {
9758                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
9759                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9760                 t->backgroundglosstexture = r_texture_black;
9761                 t->backgroundglowtexture = NULL;
9762         }
9763         t->specularpower = r_shadow_glossexponent.value;
9764         // TODO: store reference values for these in the texture?
9765         t->specularscale = 0;
9766         if (r_shadow_gloss.integer > 0)
9767         {
9768                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
9769                 {
9770                         if (r_shadow_glossintensity.value > 0)
9771                         {
9772                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
9773                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
9774                                 t->specularscale = r_shadow_glossintensity.value;
9775                         }
9776                 }
9777                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
9778                 {
9779                         t->glosstexture = r_texture_white;
9780                         t->backgroundglosstexture = r_texture_white;
9781                         t->specularscale = r_shadow_gloss2intensity.value;
9782                         t->specularpower = r_shadow_gloss2exponent.value;
9783                 }
9784         }
9785         t->specularscale *= t->specularscalemod;
9786         t->specularpower *= t->specularpowermod;
9787
9788         // lightmaps mode looks bad with dlights using actual texturing, so turn
9789         // off the colormap and glossmap, but leave the normalmap on as it still
9790         // accurately represents the shading involved
9791         if (gl_lightmaps.integer)
9792         {
9793                 t->basetexture = r_texture_grey128;
9794                 t->pantstexture = r_texture_black;
9795                 t->shirttexture = r_texture_black;
9796                 t->nmaptexture = r_texture_blanknormalmap;
9797                 t->glosstexture = r_texture_black;
9798                 t->glowtexture = NULL;
9799                 t->fogtexture = NULL;
9800                 t->reflectmasktexture = NULL;
9801                 t->backgroundbasetexture = NULL;
9802                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9803                 t->backgroundglosstexture = r_texture_black;
9804                 t->backgroundglowtexture = NULL;
9805                 t->specularscale = 0;
9806                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
9807         }
9808
9809         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
9810         VectorClear(t->dlightcolor);
9811         t->currentnumlayers = 0;
9812         if (t->currentmaterialflags & MATERIALFLAG_WALL)
9813         {
9814                 int blendfunc1, blendfunc2;
9815                 qboolean depthmask;
9816                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
9817                 {
9818                         blendfunc1 = GL_SRC_ALPHA;
9819                         blendfunc2 = GL_ONE;
9820                 }
9821                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
9822                 {
9823                         blendfunc1 = GL_SRC_ALPHA;
9824                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
9825                 }
9826                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9827                 {
9828                         blendfunc1 = t->customblendfunc[0];
9829                         blendfunc2 = t->customblendfunc[1];
9830                 }
9831                 else
9832                 {
9833                         blendfunc1 = GL_ONE;
9834                         blendfunc2 = GL_ZERO;
9835                 }
9836                 // don't colormod evilblend textures
9837                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
9838                         VectorSet(t->lightmapcolor, 1, 1, 1);
9839                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
9840                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9841                 {
9842                         // fullbright is not affected by r_refdef.lightmapintensity
9843                         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]);
9844                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9845                                 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]);
9846                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9847                                 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]);
9848                 }
9849                 else
9850                 {
9851                         vec3_t ambientcolor;
9852                         float colorscale;
9853                         // set the color tint used for lights affecting this surface
9854                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
9855                         colorscale = 2;
9856                         // q3bsp has no lightmap updates, so the lightstylevalue that
9857                         // would normally be baked into the lightmap must be
9858                         // applied to the color
9859                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
9860                         if (model->type == mod_brushq3)
9861                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
9862                         colorscale *= r_refdef.lightmapintensity;
9863                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
9864                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
9865                         // basic lit geometry
9866                         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]);
9867                         // add pants/shirt if needed
9868                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9869                                 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]);
9870                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9871                                 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]);
9872                         // now add ambient passes if needed
9873                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
9874                         {
9875                                 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]);
9876                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9877                                         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]);
9878                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9879                                         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]);
9880                         }
9881                 }
9882                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
9883                         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]);
9884                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
9885                 {
9886                         // if this is opaque use alpha blend which will darken the earlier
9887                         // passes cheaply.
9888                         //
9889                         // if this is an alpha blended material, all the earlier passes
9890                         // were darkened by fog already, so we only need to add the fog
9891                         // color ontop through the fog mask texture
9892                         //
9893                         // if this is an additive blended material, all the earlier passes
9894                         // were darkened by fog already, and we should not add fog color
9895                         // (because the background was not darkened, there is no fog color
9896                         // that was lost behind it).
9897                         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]);
9898                 }
9899         }
9900
9901         return t->currentframe;
9902 }
9903
9904 rsurfacestate_t rsurface;
9905
9906 void R_Mesh_ResizeArrays(int newvertices)
9907 {
9908         float *base;
9909         if (rsurface.array_size >= newvertices)
9910                 return;
9911         if (rsurface.array_modelvertex3f)
9912                 Mem_Free(rsurface.array_modelvertex3f);
9913         rsurface.array_size = (newvertices + 1023) & ~1023;
9914         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
9915         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
9916         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
9917         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
9918         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
9919         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
9920         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
9921         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
9922         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
9923         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
9924         rsurface.array_color4f           = base + rsurface.array_size * 27;
9925         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
9926 }
9927
9928 void RSurf_ActiveWorldEntity(void)
9929 {
9930         dp_model_t *model = r_refdef.scene.worldmodel;
9931         //if (rsurface.entity == r_refdef.scene.worldentity)
9932         //      return;
9933         rsurface.entity = r_refdef.scene.worldentity;
9934         rsurface.skeleton = NULL;
9935         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
9936         rsurface.ent_skinnum = 0;
9937         rsurface.ent_qwskin = -1;
9938         rsurface.ent_shadertime = 0;
9939         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
9940         if (rsurface.array_size < model->surfmesh.num_vertices)
9941                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9942         rsurface.matrix = identitymatrix;
9943         rsurface.inversematrix = identitymatrix;
9944         rsurface.matrixscale = 1;
9945         rsurface.inversematrixscale = 1;
9946         R_EntityMatrix(&identitymatrix);
9947         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
9948         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
9949         rsurface.fograngerecip = r_refdef.fograngerecip;
9950         rsurface.fogheightfade = r_refdef.fogheightfade;
9951         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
9952         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9953         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9954         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9955         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9956         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9957         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9958         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
9959         rsurface.colormod[3] = 1;
9960         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);
9961         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9962         rsurface.frameblend[0].lerp = 1;
9963         rsurface.ent_alttextures = false;
9964         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9965         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9966         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9967         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9968         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9969         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9970         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9971         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9972         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9973         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9974         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9975         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9976         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9977         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9978         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9979         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9980         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9981         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9982         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9983         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9984         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9985         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9986         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9987         rsurface.modelelement3i = model->surfmesh.data_element3i;
9988         rsurface.modelelement3s = model->surfmesh.data_element3s;
9989         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9990         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9991         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9992         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9993         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9994         rsurface.modelsurfaces = model->data_surfaces;
9995         rsurface.generatedvertex = false;
9996         rsurface.vertex3f  = rsurface.modelvertex3f;
9997         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9998         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9999         rsurface.svector3f = rsurface.modelsvector3f;
10000         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
10001         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10002         rsurface.tvector3f = rsurface.modeltvector3f;
10003         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
10004         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10005         rsurface.normal3f  = rsurface.modelnormal3f;
10006         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
10007         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10008         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
10009 }
10010
10011 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10012 {
10013         dp_model_t *model = ent->model;
10014         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10015         //      return;
10016         rsurface.entity = (entity_render_t *)ent;
10017         rsurface.skeleton = ent->skeleton;
10018         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10019         rsurface.ent_skinnum = ent->skinnum;
10020         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;
10021         rsurface.ent_shadertime = ent->shadertime;
10022         rsurface.ent_flags = ent->flags;
10023         if (rsurface.array_size < model->surfmesh.num_vertices)
10024                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10025         rsurface.matrix = ent->matrix;
10026         rsurface.inversematrix = ent->inversematrix;
10027         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10028         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10029         R_EntityMatrix(&rsurface.matrix);
10030         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10031         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10032         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10033         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10034         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10035         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10036         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10037         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10038         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10039         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10040         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10041         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10042         rsurface.colormod[3] = ent->alpha;
10043         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10044         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10045         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10046         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10047         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10048         if (ent->model->brush.submodel && !prepass)
10049         {
10050                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10051                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10052         }
10053         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10054         {
10055                 if (ent->animcache_vertex3f && !r_framedata_failed)
10056                 {
10057                         rsurface.modelvertex3f = ent->animcache_vertex3f;
10058                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10059                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10060                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10061                 }
10062                 else if (wanttangents)
10063                 {
10064                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10065                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10066                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10067                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10068                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
10069                 }
10070                 else if (wantnormals)
10071                 {
10072                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10073                         rsurface.modelsvector3f = NULL;
10074                         rsurface.modeltvector3f = NULL;
10075                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10076                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
10077                 }
10078                 else
10079                 {
10080                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10081                         rsurface.modelsvector3f = NULL;
10082                         rsurface.modeltvector3f = NULL;
10083                         rsurface.modelnormal3f = NULL;
10084                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
10085                 }
10086                 rsurface.modelvertex3f_bufferobject = 0;
10087                 rsurface.modelvertex3f_bufferoffset = 0;
10088                 rsurface.modelsvector3f_bufferobject = 0;
10089                 rsurface.modelsvector3f_bufferoffset = 0;
10090                 rsurface.modeltvector3f_bufferobject = 0;
10091                 rsurface.modeltvector3f_bufferoffset = 0;
10092                 rsurface.modelnormal3f_bufferobject = 0;
10093                 rsurface.modelnormal3f_bufferoffset = 0;
10094                 rsurface.generatedvertex = true;
10095         }
10096         else
10097         {
10098                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10099                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
10100                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10101                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10102                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
10103                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10104                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10105                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
10106                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10107                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10108                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
10109                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10110                 rsurface.generatedvertex = false;
10111         }
10112         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10113         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
10114         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10115         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10116         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
10117         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10118         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10119         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
10120         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10121         rsurface.modelelement3i = model->surfmesh.data_element3i;
10122         rsurface.modelelement3s = model->surfmesh.data_element3s;
10123         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
10124         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
10125         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10126         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
10127         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
10128         rsurface.modelsurfaces = model->data_surfaces;
10129         rsurface.vertex3f  = rsurface.modelvertex3f;
10130         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
10131         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
10132         rsurface.svector3f = rsurface.modelsvector3f;
10133         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
10134         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10135         rsurface.tvector3f = rsurface.modeltvector3f;
10136         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
10137         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10138         rsurface.normal3f  = rsurface.modelnormal3f;
10139         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
10140         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10141         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
10142 }
10143
10144 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)
10145 {
10146         rsurface.entity = r_refdef.scene.worldentity;
10147         rsurface.skeleton = NULL;
10148         rsurface.ent_skinnum = 0;
10149         rsurface.ent_qwskin = -1;
10150         rsurface.ent_shadertime = shadertime;
10151         rsurface.ent_flags = entflags;
10152         rsurface.modelnum_vertices = numvertices;
10153         rsurface.modelnum_triangles = numtriangles;
10154         if (rsurface.array_size < rsurface.modelnum_vertices)
10155                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
10156         rsurface.matrix = *matrix;
10157         rsurface.inversematrix = *inversematrix;
10158         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10159         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10160         R_EntityMatrix(&rsurface.matrix);
10161         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10162         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10163         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10164         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10165         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10166         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10167         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10168         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10169         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10170         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10171         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10172         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10173         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);
10174         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10175         rsurface.frameblend[0].lerp = 1;
10176         rsurface.ent_alttextures = false;
10177         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10178         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10179         if (wanttangents)
10180         {
10181                 rsurface.modelvertex3f = vertex3f;
10182                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
10183                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
10184                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10185         }
10186         else if (wantnormals)
10187         {
10188                 rsurface.modelvertex3f = vertex3f;
10189                 rsurface.modelsvector3f = NULL;
10190                 rsurface.modeltvector3f = NULL;
10191                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10192         }
10193         else
10194         {
10195                 rsurface.modelvertex3f = vertex3f;
10196                 rsurface.modelsvector3f = NULL;
10197                 rsurface.modeltvector3f = NULL;
10198                 rsurface.modelnormal3f = NULL;
10199         }
10200         rsurface.modelvertex3f_bufferobject = 0;
10201         rsurface.modelvertex3f_bufferoffset = 0;
10202         rsurface.modelsvector3f_bufferobject = 0;
10203         rsurface.modelsvector3f_bufferoffset = 0;
10204         rsurface.modeltvector3f_bufferobject = 0;
10205         rsurface.modeltvector3f_bufferoffset = 0;
10206         rsurface.modelnormal3f_bufferobject = 0;
10207         rsurface.modelnormal3f_bufferoffset = 0;
10208         rsurface.generatedvertex = true;
10209         rsurface.modellightmapcolor4f  = color4f;
10210         rsurface.modellightmapcolor4f_bufferobject = 0;
10211         rsurface.modellightmapcolor4f_bufferoffset = 0;
10212         rsurface.modeltexcoordtexture2f  = texcoord2f;
10213         rsurface.modeltexcoordtexture2f_bufferobject = 0;
10214         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10215         rsurface.modeltexcoordlightmap2f  = NULL;
10216         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
10217         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10218         rsurface.modelelement3i = element3i;
10219         rsurface.modelelement3s = element3s;
10220         rsurface.modelelement3i_bufferobject = 0;
10221         rsurface.modelelement3s_bufferobject = 0;
10222         rsurface.modellightmapoffsets = NULL;
10223         rsurface.modelsurfaces = NULL;
10224         rsurface.vertex3f  = rsurface.modelvertex3f;
10225         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
10226         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
10227         rsurface.svector3f = rsurface.modelsvector3f;
10228         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
10229         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10230         rsurface.tvector3f = rsurface.modeltvector3f;
10231         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
10232         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10233         rsurface.normal3f  = rsurface.modelnormal3f;
10234         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
10235         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10236         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
10237
10238         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
10239         {
10240                 if ((wantnormals || wanttangents) && !normal3f)
10241                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10242                 if (wanttangents && !svector3f)
10243                         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);
10244         }
10245 }
10246
10247 float RSurf_FogPoint(const float *v)
10248 {
10249         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10250         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10251         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10252         float FogHeightFade = r_refdef.fogheightfade;
10253         float fogfrac;
10254         unsigned int fogmasktableindex;
10255         if (r_refdef.fogplaneviewabove)
10256                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10257         else
10258                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10259         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10260         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10261 }
10262
10263 float RSurf_FogVertex(const float *v)
10264 {
10265         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10266         float FogPlaneViewDist = rsurface.fogplaneviewdist;
10267         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10268         float FogHeightFade = rsurface.fogheightfade;
10269         float fogfrac;
10270         unsigned int fogmasktableindex;
10271         if (r_refdef.fogplaneviewabove)
10272                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10273         else
10274                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10275         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
10276         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10277 }
10278
10279 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
10280 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
10281 {
10282         int deformindex;
10283         int texturesurfaceindex;
10284         int i, j;
10285         float amplitude;
10286         float animpos;
10287         float scale;
10288         const float *v1, *in_tc;
10289         float *out_tc;
10290         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
10291         float waveparms[4];
10292         q3shaderinfo_deform_t *deform;
10293         // 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
10294         if (rsurface.generatedvertex)
10295         {
10296                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
10297                         generatenormals = true;
10298                 for (i = 0;i < Q3MAXDEFORMS;i++)
10299                 {
10300                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
10301                         {
10302                                 generatetangents = true;
10303                                 generatenormals = true;
10304                         }
10305                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
10306                                 generatenormals = true;
10307                 }
10308                 if (generatenormals && !rsurface.modelnormal3f)
10309                 {
10310                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10311                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
10312                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
10313                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10314                 }
10315                 if (generatetangents && !rsurface.modelsvector3f)
10316                 {
10317                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10318                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
10319                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
10320                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10321                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
10322                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
10323                         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);
10324                 }
10325         }
10326         rsurface.vertex3f  = rsurface.modelvertex3f;
10327         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
10328         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
10329         rsurface.svector3f = rsurface.modelsvector3f;
10330         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
10331         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10332         rsurface.tvector3f = rsurface.modeltvector3f;
10333         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
10334         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10335         rsurface.normal3f  = rsurface.modelnormal3f;
10336         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
10337         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10338         // if vertices are deformed (sprite flares and things in maps, possibly
10339         // water waves, bulges and other deformations), generate them into
10340         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
10341         // (may be static model data or generated data for an animated model, or
10342         //  the previous deform pass)
10343         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10344         {
10345                 switch (deform->deform)
10346                 {
10347                 default:
10348                 case Q3DEFORM_PROJECTIONSHADOW:
10349                 case Q3DEFORM_TEXT0:
10350                 case Q3DEFORM_TEXT1:
10351                 case Q3DEFORM_TEXT2:
10352                 case Q3DEFORM_TEXT3:
10353                 case Q3DEFORM_TEXT4:
10354                 case Q3DEFORM_TEXT5:
10355                 case Q3DEFORM_TEXT6:
10356                 case Q3DEFORM_TEXT7:
10357                 case Q3DEFORM_NONE:
10358                         break;
10359                 case Q3DEFORM_AUTOSPRITE:
10360                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10361                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10362                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10363                         VectorNormalize(newforward);
10364                         VectorNormalize(newright);
10365                         VectorNormalize(newup);
10366                         // make deformed versions of only the model vertices used by the specified surfaces
10367                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10368                         {
10369                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10370                                 // a single autosprite surface can contain multiple sprites...
10371                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
10372                                 {
10373                                         VectorClear(center);
10374                                         for (i = 0;i < 4;i++)
10375                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
10376                                         VectorScale(center, 0.25f, center);
10377                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
10378                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
10379                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
10380                                         for (i = 0;i < 4;i++)
10381                                         {
10382                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
10383                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
10384                                         }
10385                                 }
10386                                 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);
10387                                 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);
10388                         }
10389                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10390                         rsurface.vertex3f_bufferobject = 0;
10391                         rsurface.vertex3f_bufferoffset = 0;
10392                         rsurface.svector3f = rsurface.array_deformedsvector3f;
10393                         rsurface.svector3f_bufferobject = 0;
10394                         rsurface.svector3f_bufferoffset = 0;
10395                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
10396                         rsurface.tvector3f_bufferobject = 0;
10397                         rsurface.tvector3f_bufferoffset = 0;
10398                         rsurface.normal3f = rsurface.array_deformednormal3f;
10399                         rsurface.normal3f_bufferobject = 0;
10400                         rsurface.normal3f_bufferoffset = 0;
10401                         break;
10402                 case Q3DEFORM_AUTOSPRITE2:
10403                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10404                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10405                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10406                         VectorNormalize(newforward);
10407                         VectorNormalize(newright);
10408                         VectorNormalize(newup);
10409                         // make deformed versions of only the model vertices used by the specified surfaces
10410                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10411                         {
10412                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10413                                 const float *v1, *v2;
10414                                 vec3_t start, end;
10415                                 float f, l;
10416                                 struct
10417                                 {
10418                                         float length2;
10419                                         const float *v1;
10420                                         const float *v2;
10421                                 }
10422                                 shortest[2];
10423                                 memset(shortest, 0, sizeof(shortest));
10424                                 // a single autosprite surface can contain multiple sprites...
10425                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
10426                                 {
10427                                         VectorClear(center);
10428                                         for (i = 0;i < 4;i++)
10429                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
10430                                         VectorScale(center, 0.25f, center);
10431                                         // find the two shortest edges, then use them to define the
10432                                         // axis vectors for rotating around the central axis
10433                                         for (i = 0;i < 6;i++)
10434                                         {
10435                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
10436                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
10437 #if 0
10438                                                 Debug_PolygonBegin(NULL, 0);
10439                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
10440                                                 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);
10441                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
10442                                                 Debug_PolygonEnd();
10443 #endif
10444                                                 l = VectorDistance2(v1, v2);
10445                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
10446                                                 if (v1[2] != v2[2])
10447                                                         l += (1.0f / 1024.0f);
10448                                                 if (shortest[0].length2 > l || i == 0)
10449                                                 {
10450                                                         shortest[1] = shortest[0];
10451                                                         shortest[0].length2 = l;
10452                                                         shortest[0].v1 = v1;
10453                                                         shortest[0].v2 = v2;
10454                                                 }
10455                                                 else if (shortest[1].length2 > l || i == 1)
10456                                                 {
10457                                                         shortest[1].length2 = l;
10458                                                         shortest[1].v1 = v1;
10459                                                         shortest[1].v2 = v2;
10460                                                 }
10461                                         }
10462                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
10463                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
10464 #if 0
10465                                         Debug_PolygonBegin(NULL, 0);
10466                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
10467                                         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);
10468                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
10469                                         Debug_PolygonEnd();
10470 #endif
10471                                         // this calculates the right vector from the shortest edge
10472                                         // and the up vector from the edge midpoints
10473                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
10474                                         VectorNormalize(right);
10475                                         VectorSubtract(end, start, up);
10476                                         VectorNormalize(up);
10477                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10478                                         VectorSubtract(rsurface.localvieworigin, center, forward);
10479                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10480                                         VectorNegate(forward, forward);
10481                                         VectorReflect(forward, 0, up, forward);
10482                                         VectorNormalize(forward);
10483                                         CrossProduct(up, forward, newright);
10484                                         VectorNormalize(newright);
10485 #if 0
10486                                         Debug_PolygonBegin(NULL, 0);
10487                                         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);
10488                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
10489                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
10490                                         Debug_PolygonEnd();
10491 #endif
10492 #if 0
10493                                         Debug_PolygonBegin(NULL, 0);
10494                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
10495                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
10496                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
10497                                         Debug_PolygonEnd();
10498 #endif
10499                                         // rotate the quad around the up axis vector, this is made
10500                                         // especially easy by the fact we know the quad is flat,
10501                                         // so we only have to subtract the center position and
10502                                         // measure distance along the right vector, and then
10503                                         // multiply that by the newright vector and add back the
10504                                         // center position
10505                                         // we also need to subtract the old position to undo the
10506                                         // displacement from the center, which we do with a
10507                                         // DotProduct, the subtraction/addition of center is also
10508                                         // optimized into DotProducts here
10509                                         l = DotProduct(right, center);
10510                                         for (i = 0;i < 4;i++)
10511                                         {
10512                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
10513                                                 f = DotProduct(right, v1) - l;
10514                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
10515                                         }
10516                                 }
10517                                 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);
10518                                 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);
10519                         }
10520                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10521                         rsurface.vertex3f_bufferobject = 0;
10522                         rsurface.vertex3f_bufferoffset = 0;
10523                         rsurface.svector3f = rsurface.array_deformedsvector3f;
10524                         rsurface.svector3f_bufferobject = 0;
10525                         rsurface.svector3f_bufferoffset = 0;
10526                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
10527                         rsurface.tvector3f_bufferobject = 0;
10528                         rsurface.tvector3f_bufferoffset = 0;
10529                         rsurface.normal3f = rsurface.array_deformednormal3f;
10530                         rsurface.normal3f_bufferobject = 0;
10531                         rsurface.normal3f_bufferoffset = 0;
10532                         break;
10533                 case Q3DEFORM_NORMAL:
10534                         // deform the normals to make reflections wavey
10535                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10536                         {
10537                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10538                                 for (j = 0;j < surface->num_vertices;j++)
10539                                 {
10540                                         float vertex[3];
10541                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
10542                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
10543                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
10544                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10545                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10546                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10547                                         VectorNormalize(normal);
10548                                 }
10549                                 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);
10550                         }
10551                         rsurface.svector3f = rsurface.array_deformedsvector3f;
10552                         rsurface.svector3f_bufferobject = 0;
10553                         rsurface.svector3f_bufferoffset = 0;
10554                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
10555                         rsurface.tvector3f_bufferobject = 0;
10556                         rsurface.tvector3f_bufferoffset = 0;
10557                         rsurface.normal3f = rsurface.array_deformednormal3f;
10558                         rsurface.normal3f_bufferobject = 0;
10559                         rsurface.normal3f_bufferoffset = 0;
10560                         break;
10561                 case Q3DEFORM_WAVE:
10562                         // deform vertex array to make wavey water and flags and such
10563                         waveparms[0] = deform->waveparms[0];
10564                         waveparms[1] = deform->waveparms[1];
10565                         waveparms[2] = deform->waveparms[2];
10566                         waveparms[3] = deform->waveparms[3];
10567                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10568                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10569                         // this is how a divisor of vertex influence on deformation
10570                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10571                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10572                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10573                         {
10574                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10575                                 for (j = 0;j < surface->num_vertices;j++)
10576                                 {
10577                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
10578                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
10579                                         // if the wavefunc depends on time, evaluate it per-vertex
10580                                         if (waveparms[3])
10581                                         {
10582                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
10583                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10584                                         }
10585                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
10586                                 }
10587                         }
10588                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10589                         rsurface.vertex3f_bufferobject = 0;
10590                         rsurface.vertex3f_bufferoffset = 0;
10591                         break;
10592                 case Q3DEFORM_BULGE:
10593                         // deform vertex array to make the surface have moving bulges
10594                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10595                         {
10596                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10597                                 for (j = 0;j < surface->num_vertices;j++)
10598                                 {
10599                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
10600                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
10601                                 }
10602                         }
10603                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10604                         rsurface.vertex3f_bufferobject = 0;
10605                         rsurface.vertex3f_bufferoffset = 0;
10606                         break;
10607                 case Q3DEFORM_MOVE:
10608                         // deform vertex array
10609                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10610                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10611                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10612                         VectorScale(deform->parms, scale, waveparms);
10613                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10614                         {
10615                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10616                                 for (j = 0;j < surface->num_vertices;j++)
10617                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
10618                         }
10619                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10620                         rsurface.vertex3f_bufferobject = 0;
10621                         rsurface.vertex3f_bufferoffset = 0;
10622                         break;
10623                 }
10624         }
10625         // generate texcoords based on the chosen texcoord source
10626         switch(rsurface.texture->tcgen.tcgen)
10627         {
10628         default:
10629         case Q3TCGEN_TEXTURE:
10630                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
10631                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
10632                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
10633                 break;
10634         case Q3TCGEN_LIGHTMAP:
10635                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
10636                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
10637                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
10638                 break;
10639         case Q3TCGEN_VECTOR:
10640                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10641                 {
10642                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10643                         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)
10644                         {
10645                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
10646                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
10647                         }
10648                 }
10649                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10650                 rsurface.texcoordtexture2f_bufferobject  = 0;
10651                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10652                 break;
10653         case Q3TCGEN_ENVIRONMENT:
10654                 // make environment reflections using a spheremap
10655                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10656                 {
10657                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10658                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
10659                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
10660                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
10661                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
10662                         {
10663                                 // identical to Q3A's method, but executed in worldspace so
10664                                 // carried models can be shiny too
10665
10666                                 float viewer[3], d, reflected[3], worldreflected[3];
10667
10668                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
10669                                 // VectorNormalize(viewer);
10670
10671                                 d = DotProduct(normal, viewer);
10672
10673                                 reflected[0] = normal[0]*2*d - viewer[0];
10674                                 reflected[1] = normal[1]*2*d - viewer[1];
10675                                 reflected[2] = normal[2]*2*d - viewer[2];
10676                                 // note: this is proportinal to viewer, so we can normalize later
10677
10678                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10679                                 VectorNormalize(worldreflected);
10680
10681                                 // note: this sphere map only uses world x and z!
10682                                 // so positive and negative y will LOOK THE SAME.
10683                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
10684                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
10685                         }
10686                 }
10687                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10688                 rsurface.texcoordtexture2f_bufferobject  = 0;
10689                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10690                 break;
10691         }
10692         // the only tcmod that needs software vertex processing is turbulent, so
10693         // check for it here and apply the changes if needed
10694         // and we only support that as the first one
10695         // (handling a mixture of turbulent and other tcmods would be problematic
10696         //  without punting it entirely to a software path)
10697         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10698         {
10699                 amplitude = rsurface.texture->tcmods[0].parms[1];
10700                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
10701                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10702                 {
10703                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10704                         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)
10705                         {
10706                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10707                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10708                         }
10709                 }
10710                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10711                 rsurface.texcoordtexture2f_bufferobject  = 0;
10712                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10713         }
10714         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
10715         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
10716         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10717         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
10718 }
10719
10720 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10721 {
10722         int i, j;
10723         const msurface_t *surface = texturesurfacelist[0];
10724         const msurface_t *surface2;
10725         int firstvertex;
10726         int endvertex;
10727         int numvertices;
10728         int numtriangles;
10729         // TODO: lock all array ranges before render, rather than on each surface
10730         if (texturenumsurfaces == 1)
10731                 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);
10732         else if (r_batchmode.integer == 2)
10733         {
10734                 #define MAXBATCHTRIANGLES 65536
10735                 int batchtriangles = 0;
10736                 static int batchelements[MAXBATCHTRIANGLES*3];
10737                 for (i = 0;i < texturenumsurfaces;i = j)
10738                 {
10739                         surface = texturesurfacelist[i];
10740                         j = i + 1;
10741                         if (surface->num_triangles > MAXBATCHTRIANGLES)
10742                         {
10743                                 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);
10744                                 continue;
10745                         }
10746                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10747                         batchtriangles = surface->num_triangles;
10748                         firstvertex = surface->num_firstvertex;
10749                         endvertex = surface->num_firstvertex + surface->num_vertices;
10750                         for (;j < texturenumsurfaces;j++)
10751                         {
10752                                 surface2 = texturesurfacelist[j];
10753                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10754                                         break;
10755                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10756                                 batchtriangles += surface2->num_triangles;
10757                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
10758                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10759                         }
10760                         surface2 = texturesurfacelist[j-1];
10761                         numvertices = endvertex - firstvertex;
10762                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10763                 }
10764         }
10765         else if (r_batchmode.integer == 1)
10766         {
10767                 for (i = 0;i < texturenumsurfaces;i = j)
10768                 {
10769                         surface = texturesurfacelist[i];
10770                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10771                                 if (texturesurfacelist[j] != surface2)
10772                                         break;
10773                         surface2 = texturesurfacelist[j-1];
10774                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10775                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10776                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10777                 }
10778         }
10779         else
10780         {
10781                 for (i = 0;i < texturenumsurfaces;i++)
10782                 {
10783                         surface = texturesurfacelist[i];
10784                         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);
10785                 }
10786         }
10787 }
10788
10789 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
10790 {
10791         switch(vid.renderpath)
10792         {
10793         case RENDERPATH_CGGL:
10794 #ifdef SUPPORTCG
10795                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
10796                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
10797 #endif
10798                 break;
10799         case RENDERPATH_GL20:
10800                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
10801                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
10802                 break;
10803         case RENDERPATH_GL13:
10804         case RENDERPATH_GL11:
10805                 R_Mesh_TexBind(0, surface->lightmaptexture);
10806                 break;
10807         }
10808 }
10809
10810 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
10811 {
10812         // pick the closest matching water plane and bind textures
10813         int planeindex, vertexindex;
10814         float d, bestd;
10815         vec3_t vert;
10816         const float *v;
10817         r_waterstate_waterplane_t *p, *bestp;
10818         bestd = 0;
10819         bestp = NULL;
10820         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10821         {
10822                 if(p->camera_entity != rsurface.texture->camera_entity)
10823                         continue;
10824                 d = 0;
10825                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
10826                 {
10827                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10828                         d += fabs(PlaneDiff(vert, &p->plane));
10829                 }
10830                 if (bestd > d || !bestp)
10831                 {
10832                         bestd = d;
10833                         bestp = p;
10834                 }
10835         }
10836         switch(vid.renderpath)
10837         {
10838         case RENDERPATH_CGGL:
10839 #ifdef SUPPORTCG
10840                 if (r_cg_permutation->fp_Texture_Refraction) {CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR}
10841                 else if (r_cg_permutation->fp_Texture_First) {CG_BindTexture(r_cg_permutation->fp_Texture_First, bestp ? bestp->texture_camera : r_texture_black);CHECKCGERROR}
10842                 if (r_cg_permutation->fp_Texture_Reflection) {CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR}
10843 #endif
10844                 break;
10845         case RENDERPATH_GL20:
10846                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
10847                 else if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST, bestp ? bestp->texture_camera : r_texture_black);
10848                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
10849                 break;
10850         case RENDERPATH_GL13:
10851         case RENDERPATH_GL11:
10852                 break;
10853         }
10854 }
10855
10856 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10857 {
10858         int i;
10859         const msurface_t *surface;
10860         if (r_waterstate.renderingscene)
10861                 return;
10862         for (i = 0;i < texturenumsurfaces;i++)
10863         {
10864                 surface = texturesurfacelist[i];
10865                 RSurf_BindLightmapForSurface(surface);
10866                 RSurf_BindReflectionForSurface(surface);
10867                 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);
10868         }
10869 }
10870
10871 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10872 {
10873         int i;
10874         int j;
10875         const msurface_t *surface = texturesurfacelist[0];
10876         const msurface_t *surface2;
10877         int firstvertex;
10878         int endvertex;
10879         int numvertices;
10880         int numtriangles;
10881         if (texturenumsurfaces == 1)
10882         {
10883                 RSurf_BindLightmapForSurface(surface);
10884                 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);
10885         }
10886         else if (r_batchmode.integer == 2)
10887         {
10888                 int batchtriangles = 0;
10889                 static int batchelements[MAXBATCHTRIANGLES*3];
10890                 for (i = 0;i < texturenumsurfaces;i = j)
10891                 {
10892                         surface = texturesurfacelist[i];
10893                         RSurf_BindLightmapForSurface(surface);
10894                         j = i + 1;
10895                         if (surface->num_triangles > MAXBATCHTRIANGLES)
10896                         {
10897                                 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);
10898                                 continue;
10899                         }
10900                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10901                         batchtriangles = surface->num_triangles;
10902                         firstvertex = surface->num_firstvertex;
10903                         endvertex = surface->num_firstvertex + surface->num_vertices;
10904                         for (;j < texturenumsurfaces;j++)
10905                         {
10906                                 surface2 = texturesurfacelist[j];
10907                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10908                                         break;
10909                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10910                                 batchtriangles += surface2->num_triangles;
10911                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
10912                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10913                         }
10914                         surface2 = texturesurfacelist[j-1];
10915                         numvertices = endvertex - firstvertex;
10916                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10917                 }
10918         }
10919         else if (r_batchmode.integer == 1)
10920         {
10921 #if 0
10922                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
10923                 for (i = 0;i < texturenumsurfaces;i = j)
10924                 {
10925                         surface = texturesurfacelist[i];
10926                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10927                                 if (texturesurfacelist[j] != surface2)
10928                                         break;
10929                         Con_Printf(" %i", j - i);
10930                 }
10931                 Con_Printf("\n");
10932                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
10933 #endif
10934                 for (i = 0;i < texturenumsurfaces;i = j)
10935                 {
10936                         surface = texturesurfacelist[i];
10937                         RSurf_BindLightmapForSurface(surface);
10938                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10939                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
10940                                         break;
10941 #if 0
10942                         Con_Printf(" %i", j - i);
10943 #endif
10944                         surface2 = texturesurfacelist[j-1];
10945                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10946                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10947                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10948                 }
10949 #if 0
10950                 Con_Printf("\n");
10951 #endif
10952         }
10953         else
10954         {
10955                 for (i = 0;i < texturenumsurfaces;i++)
10956                 {
10957                         surface = texturesurfacelist[i];
10958                         RSurf_BindLightmapForSurface(surface);
10959                         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);
10960                 }
10961         }
10962 }
10963
10964 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10965 {
10966         int j;
10967         int texturesurfaceindex;
10968         if (r_showsurfaces.integer == 2)
10969         {
10970                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10971                 {
10972                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10973                         for (j = 0;j < surface->num_triangles;j++)
10974                         {
10975                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
10976                                 GL_Color(f, f, f, 1);
10977                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10978                         }
10979                 }
10980         }
10981         else
10982         {
10983                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10984                 {
10985                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10986                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
10987                         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);
10988                         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);
10989                 }
10990         }
10991 }
10992
10993 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10994 {
10995         int texturesurfaceindex;
10996         int i;
10997         const float *v;
10998         float *c2;
10999         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11000         {
11001                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11002                 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)
11003                 {
11004                         c2[0] = 0.5;
11005                         c2[1] = 0.5;
11006                         c2[2] = 0.5;
11007                         c2[3] = 1;
11008                 }
11009         }
11010         rsurface.lightmapcolor4f = rsurface.array_color4f;
11011         rsurface.lightmapcolor4f_bufferobject = 0;
11012         rsurface.lightmapcolor4f_bufferoffset = 0;
11013 }
11014
11015 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11016 {
11017         int texturesurfaceindex;
11018         int i;
11019         float f;
11020         const float *v;
11021         const float *c;
11022         float *c2;
11023         if (rsurface.lightmapcolor4f)
11024         {
11025                 // generate color arrays for the surfaces in this list
11026                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11027                 {
11028                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11029                         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)
11030                         {
11031                                 f = RSurf_FogVertex(v);
11032                                 c2[0] = c[0] * f;
11033                                 c2[1] = c[1] * f;
11034                                 c2[2] = c[2] * f;
11035                                 c2[3] = c[3];
11036                         }
11037                 }
11038         }
11039         else
11040         {
11041                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11042                 {
11043                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11044                         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)
11045                         {
11046                                 f = RSurf_FogVertex(v);
11047                                 c2[0] = f;
11048                                 c2[1] = f;
11049                                 c2[2] = f;
11050                                 c2[3] = 1;
11051                         }
11052                 }
11053         }
11054         rsurface.lightmapcolor4f = rsurface.array_color4f;
11055         rsurface.lightmapcolor4f_bufferobject = 0;
11056         rsurface.lightmapcolor4f_bufferoffset = 0;
11057 }
11058
11059 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11060 {
11061         int texturesurfaceindex;
11062         int i;
11063         float f;
11064         const float *v;
11065         const float *c;
11066         float *c2;
11067         if (!rsurface.lightmapcolor4f)
11068                 return;
11069         // generate color arrays for the surfaces in this list
11070         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11071         {
11072                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11073                 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)
11074                 {
11075                         f = RSurf_FogVertex(v);
11076                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11077                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11078                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11079                         c2[3] = c[3];
11080                 }
11081         }
11082         rsurface.lightmapcolor4f = rsurface.array_color4f;
11083         rsurface.lightmapcolor4f_bufferobject = 0;
11084         rsurface.lightmapcolor4f_bufferoffset = 0;
11085 }
11086
11087 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
11088 {
11089         int texturesurfaceindex;
11090         int i;
11091         const float *c;
11092         float *c2;
11093         if (!rsurface.lightmapcolor4f)
11094                 return;
11095         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11096         {
11097                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11098                 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)
11099                 {
11100                         c2[0] = c[0] * r;
11101                         c2[1] = c[1] * g;
11102                         c2[2] = c[2] * b;
11103                         c2[3] = c[3] * a;
11104                 }
11105         }
11106         rsurface.lightmapcolor4f = rsurface.array_color4f;
11107         rsurface.lightmapcolor4f_bufferobject = 0;
11108         rsurface.lightmapcolor4f_bufferoffset = 0;
11109 }
11110
11111 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11112 {
11113         int texturesurfaceindex;
11114         int i;
11115         const float *c;
11116         float *c2;
11117         if (!rsurface.lightmapcolor4f)
11118                 return;
11119         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11120         {
11121                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11122                 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)
11123                 {
11124                         c2[0] = c[0] + r_refdef.scene.ambient;
11125                         c2[1] = c[1] + r_refdef.scene.ambient;
11126                         c2[2] = c[2] + r_refdef.scene.ambient;
11127                         c2[3] = c[3];
11128                 }
11129         }
11130         rsurface.lightmapcolor4f = rsurface.array_color4f;
11131         rsurface.lightmapcolor4f_bufferobject = 0;
11132         rsurface.lightmapcolor4f_bufferoffset = 0;
11133 }
11134
11135 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11136 {
11137         // TODO: optimize
11138         rsurface.lightmapcolor4f = NULL;
11139         rsurface.lightmapcolor4f_bufferobject = 0;
11140         rsurface.lightmapcolor4f_bufferoffset = 0;
11141         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
11142         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
11143         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11144         GL_Color(r, g, b, a);
11145         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
11146 }
11147
11148 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11149 {
11150         // TODO: optimize applyfog && applycolor case
11151         // just apply fog if necessary, and tint the fog color array if necessary
11152         rsurface.lightmapcolor4f = NULL;
11153         rsurface.lightmapcolor4f_bufferobject = 0;
11154         rsurface.lightmapcolor4f_bufferoffset = 0;
11155         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
11156         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
11157         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11158         GL_Color(r, g, b, a);
11159         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11160 }
11161
11162 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11163 {
11164         int texturesurfaceindex;
11165         int i;
11166         float *c;
11167         // TODO: optimize
11168         if (texturesurfacelist[0]->lightmapinfo)
11169         {
11170                 // generate color arrays for the surfaces in this list
11171                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11172                 {
11173                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11174                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
11175                         {
11176                                 if (surface->lightmapinfo->samples)
11177                                 {
11178                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
11179                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
11180                                         VectorScale(lm, scale, c);
11181                                         if (surface->lightmapinfo->styles[1] != 255)
11182                                         {
11183                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11184                                                 lm += size3;
11185                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
11186                                                 VectorMA(c, scale, lm, c);
11187                                                 if (surface->lightmapinfo->styles[2] != 255)
11188                                                 {
11189                                                         lm += size3;
11190                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
11191                                                         VectorMA(c, scale, lm, c);
11192                                                         if (surface->lightmapinfo->styles[3] != 255)
11193                                                         {
11194                                                                 lm += size3;
11195                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
11196                                                                 VectorMA(c, scale, lm, c);
11197                                                         }
11198                                                 }
11199                                         }
11200                                 }
11201                                 else
11202                                         VectorClear(c);
11203                                 c[3] = 1;
11204                         }
11205                 }
11206                 rsurface.lightmapcolor4f = rsurface.array_color4f;
11207                 rsurface.lightmapcolor4f_bufferobject = 0;
11208                 rsurface.lightmapcolor4f_bufferoffset = 0;
11209         }
11210         else
11211         {
11212                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
11213                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
11214                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11215         }
11216         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
11217         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
11218         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11219         GL_Color(r, g, b, a);
11220         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11221 }
11222
11223 static void RSurf_DrawBatch_GL11_ApplyFakeLight(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11224 {
11225         int texturesurfaceindex;
11226         int i;
11227         float f;
11228         const float *v;
11229         const float *n;
11230         float *c;
11231         //vec3_t eyedir;
11232
11233         // fake shading
11234         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11235         {
11236                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11237                 int numverts = surface->num_vertices;
11238                 v = rsurface.vertex3f + 3 * surface->num_firstvertex;
11239                 n = rsurface.normal3f + 3 * surface->num_firstvertex;
11240                 c = rsurface.array_color4f + 4 * surface->num_firstvertex;
11241                 for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
11242                 {
11243                         f = -DotProduct(r_refdef.view.forward, n);
11244                         f = max(0, f);
11245                         f = f * 0.85 + 0.15; // work around so stuff won't get black
11246                         f *= r_refdef.lightmapintensity;
11247                         Vector4Set(c, f, f, f, 1);
11248                 }
11249         }
11250
11251         rsurface.lightmapcolor4f = rsurface.array_color4f;
11252         rsurface.lightmapcolor4f_bufferobject = 0;
11253         rsurface.lightmapcolor4f_bufferoffset = 0;
11254 }
11255
11256 static void RSurf_DrawBatch_GL11_FakeLight(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11257 {
11258         RSurf_DrawBatch_GL11_ApplyFakeLight(texturenumsurfaces, texturesurfacelist);
11259         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
11260         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
11261         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11262         GL_Color(r, g, b, a);
11263         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11264 }
11265
11266 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
11267 {
11268         int texturesurfaceindex;
11269         int i;
11270         float f;
11271         float alpha;
11272         const float *v;
11273         const float *n;
11274         float *c;
11275         vec3_t ambientcolor;
11276         vec3_t diffusecolor;
11277         vec3_t lightdir;
11278         // TODO: optimize
11279         // model lighting
11280         VectorCopy(rsurface.modellight_lightdir, lightdir);
11281         f = 0.5f * r_refdef.lightmapintensity;
11282         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
11283         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
11284         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
11285         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
11286         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
11287         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
11288         alpha = *a;
11289         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
11290         {
11291                 // generate color arrays for the surfaces in this list
11292                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11293                 {
11294                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11295                         int numverts = surface->num_vertices;
11296                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
11297                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
11298                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
11299                         // q3-style directional shading
11300                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
11301                         {
11302                                 if ((f = DotProduct(n, lightdir)) > 0)
11303                                         VectorMA(ambientcolor, f, diffusecolor, c);
11304                                 else
11305                                         VectorCopy(ambientcolor, c);
11306                                 c[3] = alpha;
11307                         }
11308                 }
11309                 *r = 1;
11310                 *g = 1;
11311                 *b = 1;
11312                 *a = 1;
11313                 rsurface.lightmapcolor4f = rsurface.array_color4f;
11314                 rsurface.lightmapcolor4f_bufferobject = 0;
11315                 rsurface.lightmapcolor4f_bufferoffset = 0;
11316                 *applycolor = false;
11317         }
11318         else
11319         {
11320                 *r = ambientcolor[0];
11321                 *g = ambientcolor[1];
11322                 *b = ambientcolor[2];
11323                 rsurface.lightmapcolor4f = NULL;
11324                 rsurface.lightmapcolor4f_bufferobject = 0;
11325                 rsurface.lightmapcolor4f_bufferoffset = 0;
11326         }
11327 }
11328
11329 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11330 {
11331         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
11332         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
11333         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
11334         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11335         GL_Color(r, g, b, a);
11336         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11337 }
11338
11339 void RSurf_SetupDepthAndCulling(void)
11340 {
11341         // submodels are biased to avoid z-fighting with world surfaces that they
11342         // may be exactly overlapping (avoids z-fighting artifacts on certain
11343         // doors and things in Quake maps)
11344         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
11345         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
11346         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
11347         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11348 }
11349
11350 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11351 {
11352         // transparent sky would be ridiculous
11353         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11354                 return;
11355         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11356         skyrenderlater = true;
11357         RSurf_SetupDepthAndCulling();
11358         GL_DepthMask(true);
11359         // LordHavoc: HalfLife maps have freaky skypolys so don't use
11360         // skymasking on them, and Quake3 never did sky masking (unlike
11361         // software Quake and software Quake2), so disable the sky masking
11362         // in Quake3 maps as it causes problems with q3map2 sky tricks,
11363         // and skymasking also looks very bad when noclipping outside the
11364         // level, so don't use it then either.
11365         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
11366         {
11367                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
11368                 R_Mesh_ColorPointer(NULL, 0, 0);
11369                 R_Mesh_ResetTextureState();
11370                 if (skyrendermasked)
11371                 {
11372                         R_SetupShader_DepthOrShadow();
11373                         // depth-only (masking)
11374                         GL_ColorMask(0,0,0,0);
11375                         // just to make sure that braindead drivers don't draw
11376                         // anything despite that colormask...
11377                         GL_BlendFunc(GL_ZERO, GL_ONE);
11378                 }
11379                 else
11380                 {
11381                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11382                         // fog sky
11383                         GL_BlendFunc(GL_ONE, GL_ZERO);
11384                 }
11385                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11386                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11387                 if (skyrendermasked)
11388                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11389         }
11390         R_Mesh_ResetTextureState();
11391         GL_Color(1, 1, 1, 1);
11392 }
11393
11394 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
11395 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
11396 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11397 {
11398         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
11399                 return;
11400         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
11401         if (prepass)
11402         {
11403                 // render screenspace normalmap to texture
11404                 GL_DepthMask(true);
11405                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
11406                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11407         }
11408         else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
11409         {
11410                 // render water or distortion background, then blend surface on top
11411                 GL_DepthMask(true);
11412                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
11413                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
11414                 GL_DepthMask(false);
11415                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
11416                 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
11417                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
11418                 else
11419                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11420         }
11421         else
11422         {
11423                 // render surface normally
11424                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
11425                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
11426                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
11427                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
11428                 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
11429                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
11430                 else
11431                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11432         }
11433 }
11434
11435 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11436 {
11437         // OpenGL 1.3 path - anything not completely ancient
11438         int texturesurfaceindex;
11439         qboolean applycolor;
11440         qboolean applyfog;
11441         int layerindex;
11442         const texturelayer_t *layer;
11443         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11444
11445         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11446         {
11447                 vec4_t layercolor;
11448                 int layertexrgbscale;
11449                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11450                 {
11451                         if (layerindex == 0)
11452                                 GL_AlphaTest(true);
11453                         else
11454                         {
11455                                 GL_AlphaTest(false);
11456                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
11457                         }
11458                 }
11459                 GL_DepthMask(layer->depthmask && writedepth);
11460                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11461                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
11462                 {
11463                         layertexrgbscale = 4;
11464                         VectorScale(layer->color, 0.25f, layercolor);
11465                 }
11466                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
11467                 {
11468                         layertexrgbscale = 2;
11469                         VectorScale(layer->color, 0.5f, layercolor);
11470                 }
11471                 else
11472                 {
11473                         layertexrgbscale = 1;
11474                         VectorScale(layer->color, 1.0f, layercolor);
11475                 }
11476                 layercolor[3] = layer->color[3];
11477                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
11478                 R_Mesh_ColorPointer(NULL, 0, 0);
11479                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11480                 switch (layer->type)
11481                 {
11482                 case TEXTURELAYERTYPE_LITTEXTURE:
11483                         // single-pass lightmapped texture with 2x rgbscale
11484                         R_Mesh_TexBind(0, r_texture_white);
11485                         R_Mesh_TexMatrix(0, NULL);
11486                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11487                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
11488                         R_Mesh_TexBind(1, layer->texture);
11489                         R_Mesh_TexMatrix(1, &layer->texmatrix);
11490                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11491                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11492                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11493                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11494                         else if (FAKELIGHT_ENABLED)
11495                                 RSurf_DrawBatch_GL11_FakeLight(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11496                         else if (rsurface.uselightmaptexture)
11497                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11498                         else
11499                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11500                         break;
11501                 case TEXTURELAYERTYPE_TEXTURE:
11502                         // singletexture unlit texture with transparency support
11503                         R_Mesh_TexBind(0, layer->texture);
11504                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11505                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11506                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11507                         R_Mesh_TexBind(1, 0);
11508                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
11509                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11510                         break;
11511                 case TEXTURELAYERTYPE_FOG:
11512                         // singletexture fogging
11513                         if (layer->texture)
11514                         {
11515                                 R_Mesh_TexBind(0, layer->texture);
11516                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11517                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11518                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11519                         }
11520                         else
11521                         {
11522                                 R_Mesh_TexBind(0, 0);
11523                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
11524                         }
11525                         R_Mesh_TexBind(1, 0);
11526                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
11527                         // generate a color array for the fog pass
11528                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
11529                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11530                         {
11531                                 int i;
11532                                 float f;
11533                                 const float *v;
11534                                 float *c;
11535                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11536                                 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)
11537                                 {
11538                                         f = 1 - RSurf_FogVertex(v);
11539                                         c[0] = layercolor[0];
11540                                         c[1] = layercolor[1];
11541                                         c[2] = layercolor[2];
11542                                         c[3] = f * layercolor[3];
11543                                 }
11544                         }
11545                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11546                         break;
11547                 default:
11548                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11549                 }
11550         }
11551         CHECKGLERROR
11552         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11553         {
11554                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11555                 GL_AlphaTest(false);
11556         }
11557 }
11558
11559 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11560 {
11561         // OpenGL 1.1 - crusty old voodoo path
11562         int texturesurfaceindex;
11563         qboolean applyfog;
11564         int layerindex;
11565         const texturelayer_t *layer;
11566         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11567
11568         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11569         {
11570                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11571                 {
11572                         if (layerindex == 0)
11573                                 GL_AlphaTest(true);
11574                         else
11575                         {
11576                                 GL_AlphaTest(false);
11577                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
11578                         }
11579                 }
11580                 GL_DepthMask(layer->depthmask && writedepth);
11581                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11582                 R_Mesh_ColorPointer(NULL, 0, 0);
11583                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11584                 switch (layer->type)
11585                 {
11586                 case TEXTURELAYERTYPE_LITTEXTURE:
11587                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
11588                         {
11589                                 // two-pass lit texture with 2x rgbscale
11590                                 // first the lightmap pass
11591                                 R_Mesh_TexBind(0, r_texture_white);
11592                                 R_Mesh_TexMatrix(0, NULL);
11593                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11594                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
11595                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11596                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11597                                 else if (FAKELIGHT_ENABLED)
11598                                         RSurf_DrawBatch_GL11_FakeLight(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11599                                 else if (rsurface.uselightmaptexture)
11600                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11601                                 else
11602                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11603                                 // then apply the texture to it
11604                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
11605                                 R_Mesh_TexBind(0, layer->texture);
11606                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11607                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11608                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11609                                 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);
11610                         }
11611                         else
11612                         {
11613                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
11614                                 R_Mesh_TexBind(0, layer->texture);
11615                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11616                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11617                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11618                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11619                                         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);
11620                                 else
11621                                         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);
11622                         }
11623                         break;
11624                 case TEXTURELAYERTYPE_TEXTURE:
11625                         // singletexture unlit texture with transparency support
11626                         R_Mesh_TexBind(0, layer->texture);
11627                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11628                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11629                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11630                         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);
11631                         break;
11632                 case TEXTURELAYERTYPE_FOG:
11633                         // singletexture fogging
11634                         if (layer->texture)
11635                         {
11636                                 R_Mesh_TexBind(0, layer->texture);
11637                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11638                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11639                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11640                         }
11641                         else
11642                         {
11643                                 R_Mesh_TexBind(0, 0);
11644                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
11645                         }
11646                         // generate a color array for the fog pass
11647                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
11648                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11649                         {
11650                                 int i;
11651                                 float f;
11652                                 const float *v;
11653                                 float *c;
11654                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11655                                 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)
11656                                 {
11657                                         f = 1 - RSurf_FogVertex(v);
11658                                         c[0] = layer->color[0];
11659                                         c[1] = layer->color[1];
11660                                         c[2] = layer->color[2];
11661                                         c[3] = f * layer->color[3];
11662                                 }
11663                         }
11664                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11665                         break;
11666                 default:
11667                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11668                 }
11669         }
11670         CHECKGLERROR
11671         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11672         {
11673                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11674                 GL_AlphaTest(false);
11675         }
11676 }
11677
11678 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11679 {
11680         float c[4];
11681
11682         GL_AlphaTest(false);
11683         R_Mesh_ColorPointer(NULL, 0, 0);
11684         R_Mesh_ResetTextureState();
11685         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11686
11687         if(rsurface.texture && rsurface.texture->currentskinframe)
11688         {
11689                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11690                 c[3] *= rsurface.texture->currentalpha;
11691         }
11692         else
11693         {
11694                 c[0] = 1;
11695                 c[1] = 0;
11696                 c[2] = 1;
11697                 c[3] = 1;
11698         }
11699
11700         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11701         {
11702                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11703                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11704                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11705         }
11706
11707         // brighten it up (as texture value 127 means "unlit")
11708         c[0] *= 2 * r_refdef.view.colorscale;
11709         c[1] *= 2 * r_refdef.view.colorscale;
11710         c[2] *= 2 * r_refdef.view.colorscale;
11711
11712         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11713                 c[3] *= r_wateralpha.value;
11714
11715         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11716         {
11717                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11718                 GL_DepthMask(false);
11719         }
11720         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11721         {
11722                 GL_BlendFunc(GL_ONE, GL_ONE);
11723                 GL_DepthMask(false);
11724         }
11725         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11726         {
11727                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11728                 GL_DepthMask(false);
11729         }
11730         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11731         {
11732                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11733                 GL_DepthMask(false);
11734         }
11735         else
11736         {
11737                 GL_BlendFunc(GL_ONE, GL_ZERO);
11738                 GL_DepthMask(writedepth);
11739         }
11740
11741         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11742         {
11743                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11744
11745                 rsurface.lightmapcolor4f = NULL;
11746                 rsurface.lightmapcolor4f_bufferobject = 0;
11747                 rsurface.lightmapcolor4f_bufferoffset = 0;
11748         }
11749         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11750         {
11751                 qboolean applycolor = true;
11752                 float one = 1.0;
11753
11754                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11755
11756                 r_refdef.lightmapintensity = 1;
11757                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
11758                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11759         }
11760         else if (FAKELIGHT_ENABLED)
11761         {
11762                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11763
11764                 r_refdef.lightmapintensity = r_fakelight_intensity.value;
11765                 RSurf_DrawBatch_GL11_ApplyFakeLight(texturenumsurfaces, texturesurfacelist);
11766                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11767         }
11768         else
11769         {
11770                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11771
11772                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
11773                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
11774                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11775         }
11776
11777         if(!rsurface.lightmapcolor4f)
11778                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
11779
11780         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
11781         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
11782         if(r_refdef.fogenabled)
11783                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
11784
11785         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11786         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11787 }
11788
11789 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11790 {
11791         CHECKGLERROR
11792         RSurf_SetupDepthAndCulling();
11793         if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11794         {
11795                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11796                 return;
11797         }
11798         switch (vid.renderpath)
11799         {
11800         case RENDERPATH_GL20:
11801         case RENDERPATH_CGGL:
11802                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11803                 break;
11804         case RENDERPATH_GL13:
11805                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11806                 break;
11807         case RENDERPATH_GL11:
11808                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11809                 break;
11810         }
11811         CHECKGLERROR
11812 }
11813
11814 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11815 {
11816         CHECKGLERROR
11817         RSurf_SetupDepthAndCulling();
11818         if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11819         {
11820                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11821                 return;
11822         }
11823         switch (vid.renderpath)
11824         {
11825         case RENDERPATH_GL20:
11826         case RENDERPATH_CGGL:
11827                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11828                 break;
11829         case RENDERPATH_GL13:
11830                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11831                 break;
11832         case RENDERPATH_GL11:
11833                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11834                 break;
11835         }
11836         CHECKGLERROR
11837 }
11838
11839 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11840 {
11841         int i, j;
11842         int texturenumsurfaces, endsurface;
11843         texture_t *texture;
11844         const msurface_t *surface;
11845 #define MAXBATCH_TRANSPARENTSURFACES 256
11846         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
11847
11848         // if the model is static it doesn't matter what value we give for
11849         // wantnormals and wanttangents, so this logic uses only rules applicable
11850         // to a model, knowing that they are meaningless otherwise
11851         if (ent == r_refdef.scene.worldentity)
11852                 RSurf_ActiveWorldEntity();
11853         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11854                 RSurf_ActiveModelEntity(ent, false, false, false);
11855         else
11856         {
11857                 switch (vid.renderpath)
11858                 {
11859                 case RENDERPATH_GL20:
11860                 case RENDERPATH_CGGL:
11861                         RSurf_ActiveModelEntity(ent, true, true, false);
11862                         break;
11863                 case RENDERPATH_GL13:
11864                 case RENDERPATH_GL11:
11865                         RSurf_ActiveModelEntity(ent, true, false, false);
11866                         break;
11867                 }
11868         }
11869
11870         if (r_transparentdepthmasking.integer)
11871         {
11872                 qboolean setup = false;
11873                 for (i = 0;i < numsurfaces;i = j)
11874                 {
11875                         j = i + 1;
11876                         surface = rsurface.modelsurfaces + surfacelist[i];
11877                         texture = surface->texture;
11878                         rsurface.texture = R_GetCurrentTexture(texture);
11879                         // scan ahead until we find a different texture
11880                         endsurface = min(i + 1024, numsurfaces);
11881                         texturenumsurfaces = 0;
11882                         texturesurfacelist[texturenumsurfaces++] = surface;
11883                         if(FAKELIGHT_ENABLED)
11884                         {
11885                                 rsurface.uselightmaptexture = false;
11886                                 for (;j < endsurface;j++)
11887                                 {
11888                                         surface = rsurface.modelsurfaces + surfacelist[j];
11889                                         if (texture != surface->texture)
11890                                                 break;
11891                                         texturesurfacelist[texturenumsurfaces++] = surface;
11892                                 }
11893                         }
11894                         else
11895                         {
11896                                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11897                                 for (;j < endsurface;j++)
11898                                 {
11899                                         surface = rsurface.modelsurfaces + surfacelist[j];
11900                                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11901                                                 break;
11902                                         texturesurfacelist[texturenumsurfaces++] = surface;
11903                                 }
11904                         }
11905                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11906                                 continue;
11907                         // render the range of surfaces as depth
11908                         if (!setup)
11909                         {
11910                                 setup = true;
11911                                 GL_ColorMask(0,0,0,0);
11912                                 GL_Color(1,1,1,1);
11913                                 GL_DepthTest(true);
11914                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11915                                 GL_DepthMask(true);
11916                                 GL_AlphaTest(false);
11917                                 R_Mesh_ColorPointer(NULL, 0, 0);
11918                                 R_Mesh_ResetTextureState();
11919                                 R_SetupShader_DepthOrShadow();
11920                         }
11921                         RSurf_SetupDepthAndCulling();
11922                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11923                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11924                 }
11925                 if (setup)
11926                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11927         }
11928
11929         for (i = 0;i < numsurfaces;i = j)
11930         {
11931                 j = i + 1;
11932                 surface = rsurface.modelsurfaces + surfacelist[i];
11933                 texture = surface->texture;
11934                 rsurface.texture = R_GetCurrentTexture(texture);
11935                 // scan ahead until we find a different texture
11936                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
11937                 texturenumsurfaces = 0;
11938                 texturesurfacelist[texturenumsurfaces++] = surface;
11939                 if(FAKELIGHT_ENABLED)
11940                 {
11941                         rsurface.uselightmaptexture = false;
11942                         for (;j < endsurface;j++)
11943                         {
11944                                 surface = rsurface.modelsurfaces + surfacelist[j];
11945                                 if (texture != surface->texture)
11946                                         break;
11947                                 texturesurfacelist[texturenumsurfaces++] = surface;
11948                         }
11949                 }
11950                 else
11951                 {
11952                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11953                         for (;j < endsurface;j++)
11954                         {
11955                                 surface = rsurface.modelsurfaces + surfacelist[j];
11956                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11957                                         break;
11958                                 texturesurfacelist[texturenumsurfaces++] = surface;
11959                         }
11960                 }
11961                 // render the range of surfaces
11962                 if (ent == r_refdef.scene.worldentity)
11963                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11964                 else
11965                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11966         }
11967         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11968         GL_AlphaTest(false);
11969 }
11970
11971 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
11972 {
11973         // transparent surfaces get pushed off into the transparent queue
11974         int surfacelistindex;
11975         const msurface_t *surface;
11976         vec3_t tempcenter, center;
11977         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11978         {
11979                 surface = texturesurfacelist[surfacelistindex];
11980                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11981                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11982                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11983                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11984                 if (queueentity->transparent_offset) // transparent offset
11985                 {
11986                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
11987                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
11988                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
11989                 }
11990                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
11991         }
11992 }
11993
11994 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11995 {
11996         const entity_render_t *queueentity = r_refdef.scene.worldentity;
11997         CHECKGLERROR
11998         if (depthonly)
11999         {
12000                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12001                         return;
12002                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12003                         return;
12004                 RSurf_SetupDepthAndCulling();
12005                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
12006                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
12007         }
12008         else if (prepass)
12009         {
12010                 if (!rsurface.texture->currentnumlayers)
12011                         return;
12012                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12013                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12014                 else
12015                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12016         }
12017         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
12018         {
12019                 RSurf_SetupDepthAndCulling();
12020                 GL_AlphaTest(false);
12021                 R_Mesh_ColorPointer(NULL, 0, 0);
12022                 R_Mesh_ResetTextureState();
12023                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12024                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
12025                 GL_DepthMask(true);
12026                 GL_BlendFunc(GL_ONE, GL_ZERO);
12027                 GL_Color(0, 0, 0, 1);
12028                 GL_DepthTest(writedepth);
12029                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
12030         }
12031         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
12032         {
12033                 RSurf_SetupDepthAndCulling();
12034                 GL_AlphaTest(false);
12035                 R_Mesh_ColorPointer(NULL, 0, 0);
12036                 R_Mesh_ResetTextureState();
12037                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12038                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
12039                 GL_DepthMask(true);
12040                 GL_BlendFunc(GL_ONE, GL_ZERO);
12041                 GL_DepthTest(true);
12042                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
12043         }
12044         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
12045                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12046         else if (!rsurface.texture->currentnumlayers)
12047                 return;
12048         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12049         {
12050                 // in the deferred case, transparent surfaces were queued during prepass
12051                 if (!r_shadow_usingdeferredprepass)
12052                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12053         }
12054         else
12055         {
12056                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12057                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12058         }
12059         CHECKGLERROR
12060 }
12061
12062 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12063 {
12064         int i, j;
12065         texture_t *texture;
12066         // break the surface list down into batches by texture and use of lightmapping
12067         for (i = 0;i < numsurfaces;i = j)
12068         {
12069                 j = i + 1;
12070                 // texture is the base texture pointer, rsurface.texture is the
12071                 // current frame/skin the texture is directing us to use (for example
12072                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12073                 // use skin 1 instead)
12074                 texture = surfacelist[i]->texture;
12075                 rsurface.texture = R_GetCurrentTexture(texture);
12076                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12077                 {
12078                         // if this texture is not the kind we want, skip ahead to the next one
12079                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12080                                 ;
12081                         continue;
12082                 }
12083                 if(FAKELIGHT_ENABLED || depthonly || prepass)
12084                 {
12085                         rsurface.uselightmaptexture = false;
12086                         // simply scan ahead until we find a different texture or lightmap state
12087                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12088                                 ;
12089                 }
12090                 else
12091                 {
12092                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12093                         // simply scan ahead until we find a different texture or lightmap state
12094                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
12095                                 ;
12096                 }
12097                 // render the range of surfaces
12098                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12099         }
12100 }
12101
12102 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12103 {
12104         CHECKGLERROR
12105         if (depthonly)
12106         {
12107                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12108                         return;
12109                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12110                         return;
12111                 RSurf_SetupDepthAndCulling();
12112                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
12113                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
12114         }
12115         else if (prepass)
12116         {
12117                 if (!rsurface.texture->currentnumlayers)
12118                         return;
12119                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12120                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12121                 else
12122                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12123         }
12124         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
12125         {
12126                 RSurf_SetupDepthAndCulling();
12127                 GL_AlphaTest(false);
12128                 R_Mesh_ColorPointer(NULL, 0, 0);
12129                 R_Mesh_ResetTextureState();
12130                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12131                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
12132                 GL_DepthMask(true);
12133                 GL_BlendFunc(GL_ONE, GL_ZERO);
12134                 GL_Color(0, 0, 0, 1);
12135                 GL_DepthTest(writedepth);
12136                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
12137         }
12138         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12139         {
12140                 RSurf_SetupDepthAndCulling();
12141                 GL_AlphaTest(false);
12142                 R_Mesh_ColorPointer(NULL, 0, 0);
12143                 R_Mesh_ResetTextureState();
12144                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12145                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
12146                 GL_DepthMask(true);
12147                 GL_BlendFunc(GL_ONE, GL_ZERO);
12148                 GL_DepthTest(true);
12149                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
12150         }
12151         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
12152                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12153         else if (!rsurface.texture->currentnumlayers)
12154                 return;
12155         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12156         {
12157                 // in the deferred case, transparent surfaces were queued during prepass
12158                 if (!r_shadow_usingdeferredprepass)
12159                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12160         }
12161         else
12162         {
12163                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12164                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12165         }
12166         CHECKGLERROR
12167 }
12168
12169 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12170 {
12171         int i, j;
12172         texture_t *texture;
12173         // break the surface list down into batches by texture and use of lightmapping
12174         for (i = 0;i < numsurfaces;i = j)
12175         {
12176                 j = i + 1;
12177                 // texture is the base texture pointer, rsurface.texture is the
12178                 // current frame/skin the texture is directing us to use (for example
12179                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12180                 // use skin 1 instead)
12181                 texture = surfacelist[i]->texture;
12182                 rsurface.texture = R_GetCurrentTexture(texture);
12183                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12184                 {
12185                         // if this texture is not the kind we want, skip ahead to the next one
12186                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12187                                 ;
12188                         continue;
12189                 }
12190                 if(FAKELIGHT_ENABLED || depthonly || prepass)
12191                 {
12192                         rsurface.uselightmaptexture = false;
12193                         // simply scan ahead until we find a different texture or lightmap state
12194                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12195                                 ;
12196                 }
12197                 else
12198                 {
12199                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12200                         // simply scan ahead until we find a different texture or lightmap state
12201                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
12202                                 ;
12203                 }
12204                 // render the range of surfaces
12205                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12206         }
12207 }
12208
12209 float locboxvertex3f[6*4*3] =
12210 {
12211         1,0,1, 1,0,0, 1,1,0, 1,1,1,
12212         0,1,1, 0,1,0, 0,0,0, 0,0,1,
12213         1,1,1, 1,1,0, 0,1,0, 0,1,1,
12214         0,0,1, 0,0,0, 1,0,0, 1,0,1,
12215         0,0,1, 1,0,1, 1,1,1, 0,1,1,
12216         1,0,0, 0,0,0, 0,1,0, 1,1,0
12217 };
12218
12219 unsigned short locboxelements[6*2*3] =
12220 {
12221          0, 1, 2, 0, 2, 3,
12222          4, 5, 6, 4, 6, 7,
12223          8, 9,10, 8,10,11,
12224         12,13,14, 12,14,15,
12225         16,17,18, 16,18,19,
12226         20,21,22, 20,22,23
12227 };
12228
12229 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12230 {
12231         int i, j;
12232         cl_locnode_t *loc = (cl_locnode_t *)ent;
12233         vec3_t mins, size;
12234         float vertex3f[6*4*3];
12235         CHECKGLERROR
12236         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12237         GL_DepthMask(false);
12238         GL_DepthRange(0, 1);
12239         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12240         GL_DepthTest(true);
12241         GL_CullFace(GL_NONE);
12242         R_EntityMatrix(&identitymatrix);
12243
12244         R_Mesh_VertexPointer(vertex3f, 0, 0);
12245         R_Mesh_ColorPointer(NULL, 0, 0);
12246         R_Mesh_ResetTextureState();
12247         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12248
12249         i = surfacelist[0];
12250         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12251                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12252                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12253                         surfacelist[0] < 0 ? 0.5f : 0.125f);
12254
12255         if (VectorCompare(loc->mins, loc->maxs))
12256         {
12257                 VectorSet(size, 2, 2, 2);
12258                 VectorMA(loc->mins, -0.5f, size, mins);
12259         }
12260         else
12261         {
12262                 VectorCopy(loc->mins, mins);
12263                 VectorSubtract(loc->maxs, loc->mins, size);
12264         }
12265
12266         for (i = 0;i < 6*4*3;)
12267                 for (j = 0;j < 3;j++, i++)
12268                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
12269
12270         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
12271 }
12272
12273 void R_DrawLocs(void)
12274 {
12275         int index;
12276         cl_locnode_t *loc, *nearestloc;
12277         vec3_t center;
12278         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
12279         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
12280         {
12281                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
12282                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
12283         }
12284 }
12285
12286 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
12287 {
12288         if (decalsystem->decals)
12289                 Mem_Free(decalsystem->decals);
12290         memset(decalsystem, 0, sizeof(*decalsystem));
12291 }
12292
12293 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)
12294 {
12295         tridecal_t *decal;
12296         tridecal_t *decals;
12297         int i;
12298
12299         // expand or initialize the system
12300         if (decalsystem->maxdecals <= decalsystem->numdecals)
12301         {
12302                 decalsystem_t old = *decalsystem;
12303                 qboolean useshortelements;
12304                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
12305                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
12306                 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)));
12307                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
12308                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
12309                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
12310                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
12311                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
12312                 if (decalsystem->numdecals)
12313                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
12314                 if (old.decals)
12315                         Mem_Free(old.decals);
12316                 for (i = 0;i < decalsystem->maxdecals*3;i++)
12317                         decalsystem->element3i[i] = i;
12318                 if (useshortelements)
12319                         for (i = 0;i < decalsystem->maxdecals*3;i++)
12320                                 decalsystem->element3s[i] = i;
12321         }
12322
12323         // grab a decal and search for another free slot for the next one
12324         decals = decalsystem->decals;
12325         decal = decalsystem->decals + (i = decalsystem->freedecal++);
12326         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
12327                 ;
12328         decalsystem->freedecal = i;
12329         if (decalsystem->numdecals <= i)
12330                 decalsystem->numdecals = i + 1;
12331
12332         // initialize the decal
12333         decal->lived = 0;
12334         decal->triangleindex = triangleindex;
12335         decal->surfaceindex = surfaceindex;
12336         decal->decalsequence = decalsequence;
12337         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
12338         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
12339         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
12340         decal->color4ub[0][3] = 255;
12341         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
12342         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
12343         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
12344         decal->color4ub[1][3] = 255;
12345         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
12346         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
12347         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
12348         decal->color4ub[2][3] = 255;
12349         decal->vertex3f[0][0] = v0[0];
12350         decal->vertex3f[0][1] = v0[1];
12351         decal->vertex3f[0][2] = v0[2];
12352         decal->vertex3f[1][0] = v1[0];
12353         decal->vertex3f[1][1] = v1[1];
12354         decal->vertex3f[1][2] = v1[2];
12355         decal->vertex3f[2][0] = v2[0];
12356         decal->vertex3f[2][1] = v2[1];
12357         decal->vertex3f[2][2] = v2[2];
12358         decal->texcoord2f[0][0] = t0[0];
12359         decal->texcoord2f[0][1] = t0[1];
12360         decal->texcoord2f[1][0] = t1[0];
12361         decal->texcoord2f[1][1] = t1[1];
12362         decal->texcoord2f[2][0] = t2[0];
12363         decal->texcoord2f[2][1] = t2[1];
12364 }
12365
12366 extern cvar_t cl_decals_bias;
12367 extern cvar_t cl_decals_models;
12368 extern cvar_t cl_decals_newsystem_intensitymultiplier;
12369 // baseparms, parms, temps
12370 static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
12371 {
12372         int cornerindex;
12373         int index;
12374         float v[9][3];
12375         const float *vertex3f;
12376         int numpoints;
12377         float points[2][9][3];
12378         float temp[3];
12379         float tc[9][2];
12380         float f;
12381         float c[9][4];
12382         const int *e;
12383
12384         e = rsurface.modelelement3i + 3*triangleindex;
12385
12386         vertex3f = rsurface.modelvertex3f;
12387
12388         for (cornerindex = 0;cornerindex < 3;cornerindex++)
12389         {
12390                 index = 3*e[cornerindex];
12391                 VectorCopy(vertex3f + index, v[cornerindex]);
12392         }
12393         // cull backfaces
12394         //TriangleNormal(v[0], v[1], v[2], normal);
12395         //if (DotProduct(normal, localnormal) < 0.0f)
12396         //      continue;
12397         // clip by each of the box planes formed from the projection matrix
12398         // if anything survives, we emit the decal
12399         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]);
12400         if (numpoints < 3)
12401                 return;
12402         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]);
12403         if (numpoints < 3)
12404                 return;
12405         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]);
12406         if (numpoints < 3)
12407                 return;
12408         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]);
12409         if (numpoints < 3)
12410                 return;
12411         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]);
12412         if (numpoints < 3)
12413                 return;
12414         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]);
12415         if (numpoints < 3)
12416                 return;
12417         // some part of the triangle survived, so we have to accept it...
12418         if (dynamic)
12419         {
12420                 // dynamic always uses the original triangle
12421                 numpoints = 3;
12422                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
12423                 {
12424                         index = 3*e[cornerindex];
12425                         VectorCopy(vertex3f + index, v[cornerindex]);
12426                 }
12427         }
12428         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
12429         {
12430                 // convert vertex positions to texcoords
12431                 Matrix4x4_Transform(projection, v[cornerindex], temp);
12432                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
12433                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
12434                 // calculate distance fade from the projection origin
12435                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
12436                 f = bound(0.0f, f, 1.0f);
12437                 c[cornerindex][0] = r * f;
12438                 c[cornerindex][1] = g * f;
12439                 c[cornerindex][2] = b * f;
12440                 c[cornerindex][3] = 1.0f;
12441                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
12442         }
12443         if (dynamic)
12444                 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex, surfaceindex, decalsequence);
12445         else
12446                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
12447                         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);
12448 }
12449 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)
12450 {
12451         matrix4x4_t projection;
12452         decalsystem_t *decalsystem;
12453         qboolean dynamic;
12454         dp_model_t *model;
12455         const msurface_t *surface;
12456         const msurface_t *surfaces;
12457         const int *surfacelist;
12458         const texture_t *texture;
12459         int numtriangles;
12460         int numsurfacelist;
12461         int surfacelistindex;
12462         int surfaceindex;
12463         int triangleindex;
12464         float localorigin[3];
12465         float localnormal[3];
12466         float localmins[3];
12467         float localmaxs[3];
12468         float localsize;
12469         //float normal[3];
12470         float planes[6][4];
12471         float angles[3];
12472         bih_t *bih;
12473         int bih_triangles_count;
12474         int bih_triangles[256];
12475         int bih_surfaces[256];
12476
12477         decalsystem = &ent->decalsystem;
12478         model = ent->model;
12479         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
12480         {
12481                 R_DecalSystem_Reset(&ent->decalsystem);
12482                 return;
12483         }
12484
12485         if (!model->brush.data_nodes && !cl_decals_models.integer)
12486         {
12487                 if (decalsystem->model)
12488                         R_DecalSystem_Reset(decalsystem);
12489                 return;
12490         }
12491
12492         if (decalsystem->model != model)
12493                 R_DecalSystem_Reset(decalsystem);
12494         decalsystem->model = model;
12495
12496         RSurf_ActiveModelEntity(ent, false, false, false);
12497
12498         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
12499         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
12500         VectorNormalize(localnormal);
12501         localsize = worldsize*rsurface.inversematrixscale;
12502         localmins[0] = localorigin[0] - localsize;
12503         localmins[1] = localorigin[1] - localsize;
12504         localmins[2] = localorigin[2] - localsize;
12505         localmaxs[0] = localorigin[0] + localsize;
12506         localmaxs[1] = localorigin[1] + localsize;
12507         localmaxs[2] = localorigin[2] + localsize;
12508
12509         //VectorCopy(localnormal, planes[4]);
12510         //VectorVectors(planes[4], planes[2], planes[0]);
12511         AnglesFromVectors(angles, localnormal, NULL, false);
12512         AngleVectors(angles, planes[0], planes[2], planes[4]);
12513         VectorNegate(planes[0], planes[1]);
12514         VectorNegate(planes[2], planes[3]);
12515         VectorNegate(planes[4], planes[5]);
12516         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
12517         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
12518         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
12519         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
12520         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
12521         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
12522
12523 #if 1
12524 // works
12525 {
12526         matrix4x4_t forwardprojection;
12527         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
12528         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
12529 }
12530 #else
12531 // broken
12532 {
12533         float projectionvector[4][3];
12534         VectorScale(planes[0], ilocalsize, projectionvector[0]);
12535         VectorScale(planes[2], ilocalsize, projectionvector[1]);
12536         VectorScale(planes[4], ilocalsize, projectionvector[2]);
12537         projectionvector[0][0] = planes[0][0] * ilocalsize;
12538         projectionvector[0][1] = planes[1][0] * ilocalsize;
12539         projectionvector[0][2] = planes[2][0] * ilocalsize;
12540         projectionvector[1][0] = planes[0][1] * ilocalsize;
12541         projectionvector[1][1] = planes[1][1] * ilocalsize;
12542         projectionvector[1][2] = planes[2][1] * ilocalsize;
12543         projectionvector[2][0] = planes[0][2] * ilocalsize;
12544         projectionvector[2][1] = planes[1][2] * ilocalsize;
12545         projectionvector[2][2] = planes[2][2] * ilocalsize;
12546         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
12547         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
12548         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
12549         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
12550 }
12551 #endif
12552
12553         dynamic = model->surfmesh.isanimated;
12554         numsurfacelist = model->nummodelsurfaces;
12555         surfacelist = model->sortedmodelsurfaces;
12556         surfaces = model->data_surfaces;
12557
12558         bih = NULL;
12559         bih_triangles_count = -1;
12560         if(!dynamic)
12561         {
12562                 if(model->render_bih.numleafs)
12563                         bih = &model->render_bih;
12564                 else if(model->collision_bih.numleafs)
12565                         bih = &model->collision_bih;
12566         }
12567         if(bih)
12568                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
12569         if(bih_triangles_count == 0)
12570                 return;
12571         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
12572                 return;
12573         if(bih_triangles_count > 0)
12574         {
12575                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
12576                 {
12577                         surfaceindex = bih_surfaces[triangleindex];
12578                         surface = surfaces + surfaceindex;
12579                         texture = surface->texture;
12580                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12581                                 continue;
12582                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12583                                 continue;
12584                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
12585                 }
12586         }
12587         else
12588         {
12589                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
12590                 {
12591                         surfaceindex = surfacelist[surfacelistindex];
12592                         surface = surfaces + surfaceindex;
12593                         // check cull box first because it rejects more than any other check
12594                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
12595                                 continue;
12596                         // skip transparent surfaces
12597                         texture = surface->texture;
12598                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12599                                 continue;
12600                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12601                                 continue;
12602                         numtriangles = surface->num_triangles;
12603                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
12604                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
12605                 }
12606         }
12607 }
12608
12609 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12610 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)
12611 {
12612         int renderentityindex;
12613         float worldmins[3];
12614         float worldmaxs[3];
12615         entity_render_t *ent;
12616
12617         if (!cl_decals_newsystem.integer)
12618                 return;
12619
12620         worldmins[0] = worldorigin[0] - worldsize;
12621         worldmins[1] = worldorigin[1] - worldsize;
12622         worldmins[2] = worldorigin[2] - worldsize;
12623         worldmaxs[0] = worldorigin[0] + worldsize;
12624         worldmaxs[1] = worldorigin[1] + worldsize;
12625         worldmaxs[2] = worldorigin[2] + worldsize;
12626
12627         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12628
12629         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12630         {
12631                 ent = r_refdef.scene.entities[renderentityindex];
12632                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12633                         continue;
12634
12635                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12636         }
12637 }
12638
12639 typedef struct r_decalsystem_splatqueue_s
12640 {
12641         vec3_t worldorigin;
12642         vec3_t worldnormal;
12643         float color[4];
12644         float tcrange[4];
12645         float worldsize;
12646         int decalsequence;
12647 }
12648 r_decalsystem_splatqueue_t;
12649
12650 int r_decalsystem_numqueued = 0;
12651 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12652
12653 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)
12654 {
12655         r_decalsystem_splatqueue_t *queue;
12656
12657         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12658                 return;
12659
12660         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12661         VectorCopy(worldorigin, queue->worldorigin);
12662         VectorCopy(worldnormal, queue->worldnormal);
12663         Vector4Set(queue->color, r, g, b, a);
12664         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12665         queue->worldsize = worldsize;
12666         queue->decalsequence = cl.decalsequence++;
12667 }
12668
12669 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12670 {
12671         int i;
12672         r_decalsystem_splatqueue_t *queue;
12673
12674         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12675                 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);
12676         r_decalsystem_numqueued = 0;
12677 }
12678
12679 extern cvar_t cl_decals_max;
12680 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12681 {
12682         int i;
12683         decalsystem_t *decalsystem = &ent->decalsystem;
12684         int numdecals;
12685         int killsequence;
12686         tridecal_t *decal;
12687         float frametime;
12688         float lifetime;
12689
12690         if (!decalsystem->numdecals)
12691                 return;
12692
12693         if (r_showsurfaces.integer)
12694                 return;
12695
12696         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12697         {
12698                 R_DecalSystem_Reset(decalsystem);
12699                 return;
12700         }
12701
12702         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
12703         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12704
12705         if (decalsystem->lastupdatetime)
12706                 frametime = (cl.time - decalsystem->lastupdatetime);
12707         else
12708                 frametime = 0;
12709         decalsystem->lastupdatetime = cl.time;
12710         decal = decalsystem->decals;
12711         numdecals = decalsystem->numdecals;
12712
12713         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12714         {
12715                 if (decal->color4ub[0][3])
12716                 {
12717                         decal->lived += frametime;
12718                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
12719                         {
12720                                 memset(decal, 0, sizeof(*decal));
12721                                 if (decalsystem->freedecal > i)
12722                                         decalsystem->freedecal = i;
12723                         }
12724                 }
12725         }
12726         decal = decalsystem->decals;
12727         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
12728                 numdecals--;
12729
12730         // collapse the array by shuffling the tail decals into the gaps
12731         for (;;)
12732         {
12733                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
12734                         decalsystem->freedecal++;
12735                 if (decalsystem->freedecal == numdecals)
12736                         break;
12737                 decal[decalsystem->freedecal] = decal[--numdecals];
12738         }
12739
12740         decalsystem->numdecals = numdecals;
12741
12742         if (numdecals <= 0)
12743         {
12744                 // if there are no decals left, reset decalsystem
12745                 R_DecalSystem_Reset(decalsystem);
12746         }
12747 }
12748
12749 extern skinframe_t *decalskinframe;
12750 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12751 {
12752         int i;
12753         decalsystem_t *decalsystem = &ent->decalsystem;
12754         int numdecals;
12755         tridecal_t *decal;
12756         float faderate;
12757         float alpha;
12758         float *v3f;
12759         float *c4f;
12760         float *t2f;
12761         const int *e;
12762         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12763         int numtris = 0;
12764
12765         numdecals = decalsystem->numdecals;
12766         if (!numdecals)
12767                 return;
12768
12769         if (r_showsurfaces.integer)
12770                 return;
12771
12772         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12773         {
12774                 R_DecalSystem_Reset(decalsystem);
12775                 return;
12776         }
12777
12778         // if the model is static it doesn't matter what value we give for
12779         // wantnormals and wanttangents, so this logic uses only rules applicable
12780         // to a model, knowing that they are meaningless otherwise
12781         if (ent == r_refdef.scene.worldentity)
12782                 RSurf_ActiveWorldEntity();
12783         else
12784                 RSurf_ActiveModelEntity(ent, false, false, false);
12785
12786         decalsystem->lastupdatetime = cl.time;
12787         decal = decalsystem->decals;
12788
12789         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12790
12791         // update vertex positions for animated models
12792         v3f = decalsystem->vertex3f;
12793         c4f = decalsystem->color4f;
12794         t2f = decalsystem->texcoord2f;
12795         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12796         {
12797                 if (!decal->color4ub[0][3])
12798                         continue;
12799
12800                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12801                         continue;
12802
12803                 // update color values for fading decals
12804                 if (decal->lived >= cl_decals_time.value)
12805                 {
12806                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12807                         alpha *= (1.0f/255.0f);
12808                 }
12809                 else
12810                         alpha = 1.0f/255.0f;
12811
12812                 c4f[ 0] = decal->color4ub[0][0] * alpha;
12813                 c4f[ 1] = decal->color4ub[0][1] * alpha;
12814                 c4f[ 2] = decal->color4ub[0][2] * alpha;
12815                 c4f[ 3] = 1;
12816                 c4f[ 4] = decal->color4ub[1][0] * alpha;
12817                 c4f[ 5] = decal->color4ub[1][1] * alpha;
12818                 c4f[ 6] = decal->color4ub[1][2] * alpha;
12819                 c4f[ 7] = 1;
12820                 c4f[ 8] = decal->color4ub[2][0] * alpha;
12821                 c4f[ 9] = decal->color4ub[2][1] * alpha;
12822                 c4f[10] = decal->color4ub[2][2] * alpha;
12823                 c4f[11] = 1;
12824
12825                 t2f[0] = decal->texcoord2f[0][0];
12826                 t2f[1] = decal->texcoord2f[0][1];
12827                 t2f[2] = decal->texcoord2f[1][0];
12828                 t2f[3] = decal->texcoord2f[1][1];
12829                 t2f[4] = decal->texcoord2f[2][0];
12830                 t2f[5] = decal->texcoord2f[2][1];
12831
12832                 // update vertex positions for animated models
12833                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
12834                 {
12835                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12836                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
12837                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
12838                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
12839                 }
12840                 else
12841                 {
12842                         VectorCopy(decal->vertex3f[0], v3f);
12843                         VectorCopy(decal->vertex3f[1], v3f + 3);
12844                         VectorCopy(decal->vertex3f[2], v3f + 6);
12845                 }
12846
12847                 if (r_refdef.fogenabled)
12848                 {
12849                         alpha = RSurf_FogVertex(v3f);
12850                         VectorScale(c4f, alpha, c4f);
12851                         alpha = RSurf_FogVertex(v3f + 3);
12852                         VectorScale(c4f + 4, alpha, c4f + 4);
12853                         alpha = RSurf_FogVertex(v3f + 6);
12854                         VectorScale(c4f + 8, alpha, c4f + 8);
12855                 }
12856
12857                 v3f += 9;
12858                 c4f += 12;
12859                 t2f += 6;
12860                 numtris++;
12861         }
12862
12863         if (numtris > 0)
12864         {
12865                 r_refdef.stats.drawndecals += numtris;
12866
12867                 // now render the decals all at once
12868                 // (this assumes they all use one particle font texture!)
12869                 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);
12870                 R_Mesh_ResetTextureState();
12871                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
12872                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
12873                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
12874                 GL_DepthMask(false);
12875                 GL_DepthRange(0, 1);
12876                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12877                 GL_DepthTest(true);
12878                 GL_CullFace(GL_NONE);
12879                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12880                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
12881                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
12882         }
12883 }
12884
12885 static void R_DrawModelDecals(void)
12886 {
12887         int i, numdecals;
12888
12889         // fade faster when there are too many decals
12890         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12891         for (i = 0;i < r_refdef.scene.numentities;i++)
12892                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12893
12894         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12895         for (i = 0;i < r_refdef.scene.numentities;i++)
12896                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12897                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12898
12899         R_DecalSystem_ApplySplatEntitiesQueue();
12900
12901         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12902         for (i = 0;i < r_refdef.scene.numentities;i++)
12903                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12904
12905         r_refdef.stats.totaldecals += numdecals;
12906
12907         if (r_showsurfaces.integer)
12908                 return;
12909
12910         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12911
12912         for (i = 0;i < r_refdef.scene.numentities;i++)
12913         {
12914                 if (!r_refdef.viewcache.entityvisible[i])
12915                         continue;
12916                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12917                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12918         }
12919 }
12920
12921 extern cvar_t mod_collision_bih;
12922 void R_DrawDebugModel(void)
12923 {
12924         entity_render_t *ent = rsurface.entity;
12925         int i, j, k, l, flagsmask;
12926         const msurface_t *surface;
12927         dp_model_t *model = ent->model;
12928         vec3_t v;
12929
12930         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12931
12932         R_Mesh_ColorPointer(NULL, 0, 0);
12933         R_Mesh_ResetTextureState();
12934         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12935         GL_DepthRange(0, 1);
12936         GL_DepthTest(!r_showdisabledepthtest.integer);
12937         GL_DepthMask(false);
12938         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12939
12940         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12941         {
12942                 int triangleindex;
12943                 int bihleafindex;
12944                 qboolean cullbox = ent == r_refdef.scene.worldentity;
12945                 const q3mbrush_t *brush;
12946                 const bih_t *bih = &model->collision_bih;
12947                 const bih_leaf_t *bihleaf;
12948                 float vertex3f[3][3];
12949                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12950                 cullbox = false;
12951                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12952                 {
12953                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12954                                 continue;
12955                         switch (bihleaf->type)
12956                         {
12957                         case BIH_BRUSH:
12958                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12959                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12960                                 {
12961                                         R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
12962                                         GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12963                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
12964                                 }
12965                                 break;
12966                         case BIH_COLLISIONTRIANGLE:
12967                                 triangleindex = bihleaf->itemindex;
12968                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12969                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12970                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12971                                 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
12972                                 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12973                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
12974                                 break;
12975                         case BIH_RENDERTRIANGLE:
12976                                 triangleindex = bihleaf->itemindex;
12977                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12978                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12979                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12980                                 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
12981                                 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12982                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
12983                                 break;
12984                         }
12985                 }
12986         }
12987
12988         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12989
12990         if (r_showtris.integer || r_shownormals.integer)
12991         {
12992                 if (r_showdisabledepthtest.integer)
12993                 {
12994                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12995                         GL_DepthMask(false);
12996                 }
12997                 else
12998                 {
12999                         GL_BlendFunc(GL_ONE, GL_ZERO);
13000                         GL_DepthMask(true);
13001                 }
13002                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13003                 {
13004                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13005                                 continue;
13006                         rsurface.texture = R_GetCurrentTexture(surface->texture);
13007                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13008                         {
13009                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
13010                                 if (r_showtris.value > 0)
13011                                 {
13012                                         if (!rsurface.texture->currentlayers->depthmask)
13013                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13014                                         else if (ent == r_refdef.scene.worldentity)
13015                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13016                                         else
13017                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13018                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
13019                                         R_Mesh_ColorPointer(NULL, 0, 0);
13020                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
13021                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13022                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
13023                                         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);
13024                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13025                                         CHECKGLERROR
13026                                 }
13027                                 if (r_shownormals.value < 0)
13028                                 {
13029                                         qglBegin(GL_LINES);
13030                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13031                                         {
13032                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
13033                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13034                                                 qglVertex3f(v[0], v[1], v[2]);
13035                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
13036                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13037                                                 qglVertex3f(v[0], v[1], v[2]);
13038                                         }
13039                                         qglEnd();
13040                                         CHECKGLERROR
13041                                 }
13042                                 if (r_shownormals.value > 0)
13043                                 {
13044                                         qglBegin(GL_LINES);
13045                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13046                                         {
13047                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
13048                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13049                                                 qglVertex3f(v[0], v[1], v[2]);
13050                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
13051                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13052                                                 qglVertex3f(v[0], v[1], v[2]);
13053                                         }
13054                                         qglEnd();
13055                                         CHECKGLERROR
13056                                         qglBegin(GL_LINES);
13057                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13058                                         {
13059                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
13060                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13061                                                 qglVertex3f(v[0], v[1], v[2]);
13062                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
13063                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13064                                                 qglVertex3f(v[0], v[1], v[2]);
13065                                         }
13066                                         qglEnd();
13067                                         CHECKGLERROR
13068                                         qglBegin(GL_LINES);
13069                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13070                                         {
13071                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
13072                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13073                                                 qglVertex3f(v[0], v[1], v[2]);
13074                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
13075                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13076                                                 qglVertex3f(v[0], v[1], v[2]);
13077                                         }
13078                                         qglEnd();
13079                                         CHECKGLERROR
13080                                 }
13081                         }
13082                 }
13083                 rsurface.texture = NULL;
13084         }
13085 }
13086
13087 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13088 int r_maxsurfacelist = 0;
13089 const msurface_t **r_surfacelist = NULL;
13090 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13091 {
13092         int i, j, endj, flagsmask;
13093         dp_model_t *model = r_refdef.scene.worldmodel;
13094         msurface_t *surfaces;
13095         unsigned char *update;
13096         int numsurfacelist = 0;
13097         if (model == NULL)
13098                 return;
13099
13100         if (r_maxsurfacelist < model->num_surfaces)
13101         {
13102                 r_maxsurfacelist = model->num_surfaces;
13103                 if (r_surfacelist)
13104                         Mem_Free((msurface_t**)r_surfacelist);
13105                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13106         }
13107
13108         RSurf_ActiveWorldEntity();
13109
13110         surfaces = model->data_surfaces;
13111         update = model->brushq1.lightmapupdateflags;
13112
13113         // update light styles on this submodel
13114         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13115         {
13116                 model_brush_lightstyleinfo_t *style;
13117                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13118                 {
13119                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
13120                         {
13121                                 int *list = style->surfacelist;
13122                                 style->value = r_refdef.scene.lightstylevalue[style->style];
13123                                 for (j = 0;j < style->numsurfaces;j++)
13124                                         update[list[j]] = true;
13125                         }
13126                 }
13127         }
13128
13129         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13130
13131         if (debug)
13132         {
13133                 R_DrawDebugModel();
13134                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13135                 return;
13136         }
13137
13138         rsurface.uselightmaptexture = false;
13139         rsurface.texture = NULL;
13140         rsurface.rtlight = NULL;
13141         numsurfacelist = 0;
13142         // add visible surfaces to draw list
13143         for (i = 0;i < model->nummodelsurfaces;i++)
13144         {
13145                 j = model->sortedmodelsurfaces[i];
13146                 if (r_refdef.viewcache.world_surfacevisible[j])
13147                         r_surfacelist[numsurfacelist++] = surfaces + j;
13148         }
13149         // update lightmaps if needed
13150         if (model->brushq1.firstrender)
13151         {
13152                 model->brushq1.firstrender = false;
13153                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13154                         if (update[j])
13155                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13156         }
13157         else if (update)
13158         {
13159                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13160                         if (r_refdef.viewcache.world_surfacevisible[j])
13161                                 if (update[j])
13162                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13163         }
13164         // don't do anything if there were no surfaces
13165         if (!numsurfacelist)
13166         {
13167                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13168                 return;
13169         }
13170         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13171         GL_AlphaTest(false);
13172
13173         // add to stats if desired
13174         if (r_speeds.integer && !skysurfaces && !depthonly)
13175         {
13176                 r_refdef.stats.world_surfaces += numsurfacelist;
13177                 for (j = 0;j < numsurfacelist;j++)
13178                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13179         }
13180
13181         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13182 }
13183
13184 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13185 {
13186         int i, j, endj, flagsmask;
13187         dp_model_t *model = ent->model;
13188         msurface_t *surfaces;
13189         unsigned char *update;
13190         int numsurfacelist = 0;
13191         if (model == NULL)
13192                 return;
13193
13194         if (r_maxsurfacelist < model->num_surfaces)
13195         {
13196                 r_maxsurfacelist = model->num_surfaces;
13197                 if (r_surfacelist)
13198                         Mem_Free((msurface_t **)r_surfacelist);
13199                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13200         }
13201
13202         // if the model is static it doesn't matter what value we give for
13203         // wantnormals and wanttangents, so this logic uses only rules applicable
13204         // to a model, knowing that they are meaningless otherwise
13205         if (ent == r_refdef.scene.worldentity)
13206                 RSurf_ActiveWorldEntity();
13207         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13208                 RSurf_ActiveModelEntity(ent, false, false, false);
13209         else if (prepass)
13210                 RSurf_ActiveModelEntity(ent, true, true, true);
13211         else if (depthonly)
13212         {
13213                 switch (vid.renderpath)
13214                 {
13215                 case RENDERPATH_GL20:
13216                 case RENDERPATH_CGGL:
13217                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
13218                         break;
13219                 case RENDERPATH_GL13:
13220                 case RENDERPATH_GL11:
13221                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
13222                         break;
13223                 }
13224         }
13225         else
13226         {
13227                 switch (vid.renderpath)
13228                 {
13229                 case RENDERPATH_GL20:
13230                 case RENDERPATH_CGGL:
13231                         RSurf_ActiveModelEntity(ent, true, true, false);
13232                         break;
13233                 case RENDERPATH_GL13:
13234                 case RENDERPATH_GL11:
13235                         RSurf_ActiveModelEntity(ent, true, false, false);
13236                         break;
13237                 }
13238         }
13239
13240         surfaces = model->data_surfaces;
13241         update = model->brushq1.lightmapupdateflags;
13242
13243         // update light styles
13244         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13245         {
13246                 model_brush_lightstyleinfo_t *style;
13247                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13248                 {
13249                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
13250                         {
13251                                 int *list = style->surfacelist;
13252                                 style->value = r_refdef.scene.lightstylevalue[style->style];
13253                                 for (j = 0;j < style->numsurfaces;j++)
13254                                         update[list[j]] = true;
13255                         }
13256                 }
13257         }
13258
13259         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13260
13261         if (debug)
13262         {
13263                 R_DrawDebugModel();
13264                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13265                 return;
13266         }
13267
13268         rsurface.uselightmaptexture = false;
13269         rsurface.texture = NULL;
13270         rsurface.rtlight = NULL;
13271         numsurfacelist = 0;
13272         // add visible surfaces to draw list
13273         for (i = 0;i < model->nummodelsurfaces;i++)
13274                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
13275         // don't do anything if there were no surfaces
13276         if (!numsurfacelist)
13277         {
13278                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13279                 return;
13280         }
13281         // update lightmaps if needed
13282         if (update)
13283         {
13284                 int updated = 0;
13285                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13286                 {
13287                         if (update[j])
13288                         {
13289                                 updated++;
13290                                 R_BuildLightMap(ent, surfaces + j);
13291                         }
13292                 }
13293         }
13294         if (update)
13295                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13296                         if (update[j])
13297                                 R_BuildLightMap(ent, surfaces + j);
13298         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13299         GL_AlphaTest(false);
13300
13301         // add to stats if desired
13302         if (r_speeds.integer && !skysurfaces && !depthonly)
13303         {
13304                 r_refdef.stats.entities_surfaces += numsurfacelist;
13305                 for (j = 0;j < numsurfacelist;j++)
13306                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
13307         }
13308
13309         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13310 }
13311
13312 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
13313 {
13314         static texture_t texture;
13315         static msurface_t surface;
13316         const msurface_t *surfacelist = &surface;
13317
13318         // fake enough texture and surface state to render this geometry
13319
13320         texture.update_lastrenderframe = -1; // regenerate this texture
13321         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
13322         texture.currentskinframe = skinframe;
13323         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
13324         texture.offsetmapping = OFFSETMAPPING_OFF;
13325         texture.offsetscale = 1;
13326         texture.specularscalemod = 1;
13327         texture.specularpowermod = 1;
13328
13329         surface.texture = &texture;
13330         surface.num_triangles = numtriangles;
13331         surface.num_firsttriangle = firsttriangle;
13332         surface.num_vertices = numvertices;
13333         surface.num_firstvertex = firstvertex;
13334
13335         // now render it
13336         rsurface.texture = R_GetCurrentTexture(surface.texture);
13337         rsurface.uselightmaptexture = false;
13338         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
13339 }
13340
13341 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)
13342 {
13343         static msurface_t surface;
13344         const msurface_t *surfacelist = &surface;
13345
13346         // fake enough texture and surface state to render this geometry
13347
13348         surface.texture = texture;
13349         surface.num_triangles = numtriangles;
13350         surface.num_firsttriangle = firsttriangle;
13351         surface.num_vertices = numvertices;
13352         surface.num_firstvertex = firstvertex;
13353
13354         // now render it
13355         rsurface.texture = R_GetCurrentTexture(surface.texture);
13356         rsurface.uselightmaptexture = false;
13357         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
13358 }