]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
first draft of sobel operator, use r_glsl_postprocess_uservec1 with an x value > 100
[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_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
80 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
81 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
82 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)"};
83 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)"};
84 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
85 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
86 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
87 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
88 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
89 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
90 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
91 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."};
92 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
93 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
94 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
95 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."};
96 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
97 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
98 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
99 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
100 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"};
101 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"};
102 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
103 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
104 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
105 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
106 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"};
107
108 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
109 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
110 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
111 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
112 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
113 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
114 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
115 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
116
117 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)"};
118 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"};
119
120 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
121 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
122 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
123 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
124 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
125
126 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
127 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
128 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
129
130 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)"};
131 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
132 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
133 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
134 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
135 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)"};
136 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)"};
137 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)"};
138 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)"};
139
140 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)"};
141 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
142 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"};
143 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
144 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
145
146 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
147 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
148 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
149 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
150
151 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
152 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
153 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
154 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
155 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
156 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
157 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
158
159 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
160 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
161 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
162 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)"};
163
164 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"};
165
166 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"};
167
168 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
169
170 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
171 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
172 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"};
173 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
174 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
175 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
176 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
177 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)"};
178
179 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
180
181 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)"};
182
183 extern cvar_t v_glslgamma;
184
185 extern qboolean v_flipped_state;
186
187 static struct r_bloomstate_s
188 {
189         qboolean enabled;
190         qboolean hdr;
191
192         int bloomwidth, bloomheight;
193
194         int screentexturewidth, screentextureheight;
195         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
196
197         int bloomtexturewidth, bloomtextureheight;
198         rtexture_t *texture_bloom;
199
200         // arrays for rendering the screen passes
201         float screentexcoord2f[8];
202         float bloomtexcoord2f[8];
203         float offsettexcoord2f[8];
204
205         r_viewport_t viewport;
206 }
207 r_bloomstate;
208
209 r_waterstate_t r_waterstate;
210
211 /// shadow volume bsp struct with automatically growing nodes buffer
212 svbsp_t r_svbsp;
213
214 rtexture_t *r_texture_blanknormalmap;
215 rtexture_t *r_texture_white;
216 rtexture_t *r_texture_grey128;
217 rtexture_t *r_texture_black;
218 rtexture_t *r_texture_notexture;
219 rtexture_t *r_texture_whitecube;
220 rtexture_t *r_texture_normalizationcube;
221 rtexture_t *r_texture_fogattenuation;
222 rtexture_t *r_texture_fogheighttexture;
223 rtexture_t *r_texture_gammaramps;
224 unsigned int r_texture_gammaramps_serial;
225 //rtexture_t *r_texture_fogintensity;
226 rtexture_t *r_texture_reflectcube;
227
228 // TODO: hash lookups?
229 typedef struct cubemapinfo_s
230 {
231         char basename[64];
232         rtexture_t *texture;
233 }
234 cubemapinfo_t;
235
236 int r_texture_numcubemaps;
237 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
238
239 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
240 unsigned int r_numqueries;
241 unsigned int r_maxqueries;
242
243 typedef struct r_qwskincache_s
244 {
245         char name[MAX_QPATH];
246         skinframe_t *skinframe;
247 }
248 r_qwskincache_t;
249
250 static r_qwskincache_t *r_qwskincache;
251 static int r_qwskincache_size;
252
253 /// vertex coordinates for a quad that covers the screen exactly
254 const float r_screenvertex3f[12] =
255 {
256         0, 0, 0,
257         1, 0, 0,
258         1, 1, 0,
259         0, 1, 0
260 };
261
262 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
263 {
264         int i;
265         for (i = 0;i < verts;i++)
266         {
267                 out[0] = in[0] * r;
268                 out[1] = in[1] * g;
269                 out[2] = in[2] * b;
270                 out[3] = in[3];
271                 in += 4;
272                 out += 4;
273         }
274 }
275
276 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
277 {
278         int i;
279         for (i = 0;i < verts;i++)
280         {
281                 out[0] = r;
282                 out[1] = g;
283                 out[2] = b;
284                 out[3] = a;
285                 out += 4;
286         }
287 }
288
289 // FIXME: move this to client?
290 void FOG_clear(void)
291 {
292         if (gamemode == GAME_NEHAHRA)
293         {
294                 Cvar_Set("gl_fogenable", "0");
295                 Cvar_Set("gl_fogdensity", "0.2");
296                 Cvar_Set("gl_fogred", "0.3");
297                 Cvar_Set("gl_foggreen", "0.3");
298                 Cvar_Set("gl_fogblue", "0.3");
299         }
300         r_refdef.fog_density = 0;
301         r_refdef.fog_red = 0;
302         r_refdef.fog_green = 0;
303         r_refdef.fog_blue = 0;
304         r_refdef.fog_alpha = 1;
305         r_refdef.fog_start = 0;
306         r_refdef.fog_end = 16384;
307         r_refdef.fog_height = 1<<30;
308         r_refdef.fog_fadedepth = 128;
309         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
310 }
311
312 static void R_BuildBlankTextures(void)
313 {
314         unsigned char data[4];
315         data[2] = 128; // normal X
316         data[1] = 128; // normal Y
317         data[0] = 255; // normal Z
318         data[3] = 128; // height
319         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
320         data[0] = 255;
321         data[1] = 255;
322         data[2] = 255;
323         data[3] = 255;
324         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
325         data[0] = 128;
326         data[1] = 128;
327         data[2] = 128;
328         data[3] = 255;
329         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
330         data[0] = 0;
331         data[1] = 0;
332         data[2] = 0;
333         data[3] = 255;
334         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
335 }
336
337 static void R_BuildNoTexture(void)
338 {
339         int x, y;
340         unsigned char pix[16][16][4];
341         // this makes a light grey/dark grey checkerboard texture
342         for (y = 0;y < 16;y++)
343         {
344                 for (x = 0;x < 16;x++)
345                 {
346                         if ((y < 8) ^ (x < 8))
347                         {
348                                 pix[y][x][0] = 128;
349                                 pix[y][x][1] = 128;
350                                 pix[y][x][2] = 128;
351                                 pix[y][x][3] = 255;
352                         }
353                         else
354                         {
355                                 pix[y][x][0] = 64;
356                                 pix[y][x][1] = 64;
357                                 pix[y][x][2] = 64;
358                                 pix[y][x][3] = 255;
359                         }
360                 }
361         }
362         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
363 }
364
365 static void R_BuildWhiteCube(void)
366 {
367         unsigned char data[6*1*1*4];
368         memset(data, 255, sizeof(data));
369         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
370 }
371
372 static void R_BuildNormalizationCube(void)
373 {
374         int x, y, side;
375         vec3_t v;
376         vec_t s, t, intensity;
377 #define NORMSIZE 64
378         unsigned char *data;
379         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
380         for (side = 0;side < 6;side++)
381         {
382                 for (y = 0;y < NORMSIZE;y++)
383                 {
384                         for (x = 0;x < NORMSIZE;x++)
385                         {
386                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
387                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
388                                 switch(side)
389                                 {
390                                 default:
391                                 case 0:
392                                         v[0] = 1;
393                                         v[1] = -t;
394                                         v[2] = -s;
395                                         break;
396                                 case 1:
397                                         v[0] = -1;
398                                         v[1] = -t;
399                                         v[2] = s;
400                                         break;
401                                 case 2:
402                                         v[0] = s;
403                                         v[1] = 1;
404                                         v[2] = t;
405                                         break;
406                                 case 3:
407                                         v[0] = s;
408                                         v[1] = -1;
409                                         v[2] = -t;
410                                         break;
411                                 case 4:
412                                         v[0] = s;
413                                         v[1] = -t;
414                                         v[2] = 1;
415                                         break;
416                                 case 5:
417                                         v[0] = -s;
418                                         v[1] = -t;
419                                         v[2] = -1;
420                                         break;
421                                 }
422                                 intensity = 127.0f / sqrt(DotProduct(v, v));
423                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
424                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
425                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
426                                 data[((side*64+y)*64+x)*4+3] = 255;
427                         }
428                 }
429         }
430         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
431         Mem_Free(data);
432 }
433
434 static void R_BuildFogTexture(void)
435 {
436         int x, b;
437 #define FOGWIDTH 256
438         unsigned char data1[FOGWIDTH][4];
439         //unsigned char data2[FOGWIDTH][4];
440         double d, r, alpha;
441
442         r_refdef.fogmasktable_start = r_refdef.fog_start;
443         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
444         r_refdef.fogmasktable_range = r_refdef.fogrange;
445         r_refdef.fogmasktable_density = r_refdef.fog_density;
446
447         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
448         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
449         {
450                 d = (x * r - r_refdef.fogmasktable_start);
451                 if(developer_extra.integer)
452                         Con_DPrintf("%f ", d);
453                 d = max(0, d);
454                 if (r_fog_exp2.integer)
455                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
456                 else
457                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
458                 if(developer_extra.integer)
459                         Con_DPrintf(" : %f ", alpha);
460                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
461                 if(developer_extra.integer)
462                         Con_DPrintf(" = %f\n", alpha);
463                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
464         }
465
466         for (x = 0;x < FOGWIDTH;x++)
467         {
468                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
469                 data1[x][0] = b;
470                 data1[x][1] = b;
471                 data1[x][2] = b;
472                 data1[x][3] = 255;
473                 //data2[x][0] = 255 - b;
474                 //data2[x][1] = 255 - b;
475                 //data2[x][2] = 255 - b;
476                 //data2[x][3] = 255;
477         }
478         if (r_texture_fogattenuation)
479         {
480                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
481                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
482         }
483         else
484         {
485                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
486                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
487         }
488 }
489
490 static void R_BuildFogHeightTexture(void)
491 {
492         unsigned char *inpixels;
493         int size;
494         int x;
495         int y;
496         int j;
497         float c[4];
498         float f;
499         inpixels = NULL;
500         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
501         if (r_refdef.fogheighttexturename[0])
502                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false);
503         if (!inpixels)
504         {
505                 r_refdef.fog_height_tablesize = 0;
506                 if (r_texture_fogheighttexture)
507                         R_FreeTexture(r_texture_fogheighttexture);
508                 r_texture_fogheighttexture = NULL;
509                 if (r_refdef.fog_height_table2d)
510                         Mem_Free(r_refdef.fog_height_table2d);
511                 r_refdef.fog_height_table2d = NULL;
512                 if (r_refdef.fog_height_table1d)
513                         Mem_Free(r_refdef.fog_height_table1d);
514                 r_refdef.fog_height_table1d = NULL;
515                 return;
516         }
517         size = image_width;
518         r_refdef.fog_height_tablesize = size;
519         r_refdef.fog_height_table1d = Mem_Alloc(r_main_mempool, size * 4);
520         r_refdef.fog_height_table2d = Mem_Alloc(r_main_mempool, size * size * 4);
521         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
522         Mem_Free(inpixels);
523         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
524         // average fog color table accounting for every fog layer between a point
525         // and the camera.  (Note: attenuation is handled separately!)
526         for (y = 0;y < size;y++)
527         {
528                 for (x = 0;x < size;x++)
529                 {
530                         Vector4Clear(c);
531                         f = 0;
532                         if (x < y)
533                         {
534                                 for (j = x;j <= y;j++)
535                                 {
536                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
537                                         f++;
538                                 }
539                         }
540                         else
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                         f = 1.0f / f;
549                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
550                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
551                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
552                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
553                 }
554         }
555         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, NULL);
556 }
557
558 //=======================================================================================================================================================
559
560 static const char *builtinshaderstring =
561 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
562 "// written by Forest 'LordHavoc' Hale\n"
563 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
564 "\n"
565 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
566 "# define USEFOG\n"
567 "#endif\n"
568 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
569 "#define USELIGHTMAP\n"
570 "#endif\n"
571 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
572 "#define USEEYEVECTOR\n"
573 "#endif\n"
574 "\n"
575 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
576 "# extension GL_ARB_texture_rectangle : enable\n"
577 "#endif\n"
578 "\n"
579 "#ifdef USESHADOWMAP2D\n"
580 "# ifdef GL_EXT_gpu_shader4\n"
581 "#   extension GL_EXT_gpu_shader4 : enable\n"
582 "# endif\n"
583 "# ifdef GL_ARB_texture_gather\n"
584 "#   extension GL_ARB_texture_gather : enable\n"
585 "# else\n"
586 "#   ifdef GL_AMD_texture_texture4\n"
587 "#     extension GL_AMD_texture_texture4 : enable\n"
588 "#   endif\n"
589 "# endif\n"
590 "#endif\n"
591 "\n"
592 "#ifdef USESHADOWMAPCUBE\n"
593 "# extension GL_EXT_gpu_shader4 : enable\n"
594 "#endif\n"
595 "\n"
596 "//#ifdef USESHADOWSAMPLER\n"
597 "//# extension GL_ARB_shadow : enable\n"
598 "//#endif\n"
599 "\n"
600 "//#ifdef __GLSL_CG_DATA_TYPES\n"
601 "//# define myhalf half\n"
602 "//# define myhalf2 half2\n"
603 "//# define myhalf3 half3\n"
604 "//# define myhalf4 half4\n"
605 "//#else\n"
606 "# define myhalf float\n"
607 "# define myhalf2 vec2\n"
608 "# define myhalf3 vec3\n"
609 "# define myhalf4 vec4\n"
610 "//#endif\n"
611 "\n"
612 "#ifdef VERTEX_SHADER\n"
613 "uniform mat4 ModelViewProjectionMatrix;\n"
614 "#endif\n"
615 "\n"
616 "#ifdef MODE_DEPTH_OR_SHADOW\n"
617 "#ifdef VERTEX_SHADER\n"
618 "void main(void)\n"
619 "{\n"
620 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
621 "}\n"
622 "#endif\n"
623 "#else // !MODE_DEPTH_ORSHADOW\n"
624 "\n"
625 "\n"
626 "\n"
627 "\n"
628 "#ifdef MODE_SHOWDEPTH\n"
629 "#ifdef VERTEX_SHADER\n"
630 "void main(void)\n"
631 "{\n"
632 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
633 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
634 "}\n"
635 "#endif\n"
636 "\n"
637 "#ifdef FRAGMENT_SHADER\n"
638 "void main(void)\n"
639 "{\n"
640 "       gl_FragColor = gl_Color;\n"
641 "}\n"
642 "#endif\n"
643 "#else // !MODE_SHOWDEPTH\n"
644 "\n"
645 "\n"
646 "\n"
647 "\n"
648 "#ifdef MODE_POSTPROCESS\n"
649 "varying vec2 TexCoord1;\n"
650 "varying vec2 TexCoord2;\n"
651 "\n"
652 "#ifdef VERTEX_SHADER\n"
653 "void main(void)\n"
654 "{\n"
655 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
656 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
657 "#ifdef USEBLOOM\n"
658 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
659 "#endif\n"
660 "}\n"
661 "#endif\n"
662 "\n"
663 "#ifdef FRAGMENT_SHADER\n"
664 "uniform sampler2D Texture_First;\n"
665 "#ifdef USEBLOOM\n"
666 "uniform sampler2D Texture_Second;\n"
667 "#endif\n"
668 "#ifdef USEGAMMARAMPS\n"
669 "uniform sampler2D Texture_GammaRamps;\n"
670 "#endif\n"
671 "#ifdef USESATURATION\n"
672 "uniform float Saturation;\n"
673 "#endif\n"
674 "#ifdef USEVIEWTINT\n"
675 "uniform vec4 ViewTintColor;\n"
676 "#endif\n"
677 "//uncomment these if you want to use them:\n"
678 "uniform vec4 UserVec1;\n"
679 "// uniform vec4 UserVec2;\n"
680 "// uniform vec4 UserVec3;\n"
681 "// uniform vec4 UserVec4;\n"
682 "// uniform float ClientTime;\n"
683 "uniform vec2 PixelSize;\n"
684 "void main(void)\n"
685 "{\n"
686 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
687 "#ifdef USEBLOOM\n"
688 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
689 "#endif\n"
690 "#ifdef USEVIEWTINT\n"
691 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
692 "#endif\n"
693 "\n"
694 "#ifdef USEPOSTPROCESSING\n"
695 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
696 "// 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"
697 "       if (UserVec1.x > 100.0) {\n"
698 "               // vec2 ts = textureSize(Texture_First, 0);\n"
699 "               // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
700 "               vec2 px = PixelSize;\n"
701 "               vec4 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y));\n"
702 "               vec4 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0));\n"
703 "               vec4 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y));\n"
704 "               vec4 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y));\n"
705 "               vec4 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0));\n"
706 "               vec4 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y));\n"
707 "               vec4 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y));\n"
708 "               vec4 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y));\n"
709 "               vec4 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y));\n"
710 "               vec4 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y));\n"
711 "               vec4 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y));\n"
712 "               vec4 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y));\n"
713 ""
714 "               float px1 = -1.0 * (0.30*x1.r + 0.59*x1.g + 0.11*x1.b);\n"
715 "               float px2 = -2.0 * (0.30*x2.r + 0.59*x2.g + 0.11*x2.b);\n"
716 "               float px3 = -1.0 * (0.30*x3.r + 0.59*x3.g + 0.11*x3.b);\n"
717 "               float px4 =  1.0 * (0.30*x4.r + 0.59*x4.g + 0.11*x4.b);\n"
718 "               float px5 =  2.0 * (0.30*x5.r + 0.59*x5.g + 0.11*x5.b);\n"
719 "               float px6 =  1.0 * (0.30*x6.r + 0.59*x6.g + 0.11*x6.b);\n"
720 "               float py1 = -1.0 * (0.30*y1.r + 0.59*y1.g + 0.11*y1.b);\n"
721 "               float py2 = -2.0 * (0.30*y2.r + 0.59*y2.g + 0.11*y2.b);\n"
722 "               float py3 = -1.0 * (0.30*y3.r + 0.59*y3.g + 0.11*y3.b);\n"
723 "               float py4 =  1.0 * (0.30*y4.r + 0.59*y4.g + 0.11*y4.b);\n"
724 "               float py5 =  2.0 * (0.30*y5.r + 0.59*y5.g + 0.11*y5.b);\n"
725 "               float py6 =  1.0 * (0.30*y6.r + 0.59*y6.g + 0.11*y6.b);\n"
726 "               gl_FragColor = 0.25 * vec4(vec3(abs(px1 + px2 + px3 + px4 + px5 + px6)), 1) + 0.25 * vec4(vec3(abs(py1 + py2 + py3 + py4 + py5 + py6)), 1);\n"
727 "       } else {\n"
728 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
729 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
730 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
731 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
732 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
733 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
734 "       }\n"
735 "#endif\n"
736 "\n"
737 "#ifdef USESATURATION\n"
738 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
739 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
740 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
741 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
742 "#endif\n"
743 "\n"
744 "#ifdef USEGAMMARAMPS\n"
745 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
746 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
747 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
748 "#endif\n"
749 "}\n"
750 "#endif\n"
751 "#else // !MODE_POSTPROCESS\n"
752 "\n"
753 "\n"
754 "\n"
755 "\n"
756 "#ifdef MODE_GENERIC\n"
757 "#ifdef USEDIFFUSE\n"
758 "varying vec2 TexCoord1;\n"
759 "#endif\n"
760 "#ifdef USESPECULAR\n"
761 "varying vec2 TexCoord2;\n"
762 "#endif\n"
763 "#ifdef VERTEX_SHADER\n"
764 "void main(void)\n"
765 "{\n"
766 "       gl_FrontColor = gl_Color;\n"
767 "#ifdef USEDIFFUSE\n"
768 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
769 "#endif\n"
770 "#ifdef USESPECULAR\n"
771 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
772 "#endif\n"
773 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
774 "}\n"
775 "#endif\n"
776 "\n"
777 "#ifdef FRAGMENT_SHADER\n"
778 "#ifdef USEDIFFUSE\n"
779 "uniform sampler2D Texture_First;\n"
780 "#endif\n"
781 "#ifdef USESPECULAR\n"
782 "uniform sampler2D Texture_Second;\n"
783 "#endif\n"
784 "\n"
785 "void main(void)\n"
786 "{\n"
787 "       gl_FragColor = gl_Color;\n"
788 "#ifdef USEDIFFUSE\n"
789 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
790 "#endif\n"
791 "\n"
792 "#ifdef USESPECULAR\n"
793 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
794 "# ifdef USECOLORMAPPING\n"
795 "       gl_FragColor *= tex2;\n"
796 "# endif\n"
797 "# ifdef USEGLOW\n"
798 "       gl_FragColor += tex2;\n"
799 "# endif\n"
800 "# ifdef USEVERTEXTEXTUREBLEND\n"
801 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
802 "# endif\n"
803 "#endif\n"
804 "}\n"
805 "#endif\n"
806 "#else // !MODE_GENERIC\n"
807 "\n"
808 "\n"
809 "\n"
810 "\n"
811 "#ifdef MODE_BLOOMBLUR\n"
812 "varying TexCoord;\n"
813 "#ifdef VERTEX_SHADER\n"
814 "void main(void)\n"
815 "{\n"
816 "       gl_FrontColor = gl_Color;\n"
817 "       TexCoord = gl_MultiTexCoord0.xy;\n"
818 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
819 "}\n"
820 "#endif\n"
821 "\n"
822 "#ifdef FRAGMENT_SHADER\n"
823 "uniform sampler2D Texture_First;\n"
824 "uniform vec4 BloomBlur_Parameters;\n"
825 "\n"
826 "void main(void)\n"
827 "{\n"
828 "       int i;\n"
829 "       vec2 tc = TexCoord;\n"
830 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
831 "       tc += BloomBlur_Parameters.xy;\n"
832 "       for (i = 1;i < SAMPLES;i++)\n"
833 "       {\n"
834 "               color += texture2D(Texture_First, tc).rgb;\n"
835 "               tc += BloomBlur_Parameters.xy;\n"
836 "       }\n"
837 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
838 "}\n"
839 "#endif\n"
840 "#else // !MODE_BLOOMBLUR\n"
841 "#ifdef MODE_REFRACTION\n"
842 "varying vec2 TexCoord;\n"
843 "varying vec4 ModelViewProjectionPosition;\n"
844 "uniform mat4 TexMatrix;\n"
845 "#ifdef VERTEX_SHADER\n"
846 "\n"
847 "void main(void)\n"
848 "{\n"
849 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
850 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
851 "       ModelViewProjectionPosition = gl_Position;\n"
852 "}\n"
853 "#endif\n"
854 "\n"
855 "#ifdef FRAGMENT_SHADER\n"
856 "uniform sampler2D Texture_Normal;\n"
857 "uniform sampler2D Texture_Refraction;\n"
858 "uniform sampler2D Texture_Reflection;\n"
859 "\n"
860 "uniform vec4 DistortScaleRefractReflect;\n"
861 "uniform vec4 ScreenScaleRefractReflect;\n"
862 "uniform vec4 ScreenCenterRefractReflect;\n"
863 "uniform vec4 RefractColor;\n"
864 "uniform vec4 ReflectColor;\n"
865 "uniform float ReflectFactor;\n"
866 "uniform float ReflectOffset;\n"
867 "\n"
868 "void main(void)\n"
869 "{\n"
870 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
871 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
872 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
873 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
874 "       // FIXME temporary hack to detect the case that the reflection\n"
875 "       // gets blackened at edges due to leaving the area that contains actual\n"
876 "       // content.\n"
877 "       // Remove this 'ack once we have a better way to stop this thing from\n"
878 "       // 'appening.\n"
879 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
880 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
881 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
882 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
883 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
884 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
885 "}\n"
886 "#endif\n"
887 "#else // !MODE_REFRACTION\n"
888 "\n"
889 "\n"
890 "\n"
891 "\n"
892 "#ifdef MODE_WATER\n"
893 "varying vec2 TexCoord;\n"
894 "varying vec3 EyeVector;\n"
895 "varying vec4 ModelViewProjectionPosition;\n"
896 "#ifdef VERTEX_SHADER\n"
897 "uniform vec3 EyePosition;\n"
898 "uniform mat4 TexMatrix;\n"
899 "\n"
900 "void main(void)\n"
901 "{\n"
902 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
903 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
904 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
905 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
906 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
907 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
908 "       ModelViewProjectionPosition = gl_Position;\n"
909 "}\n"
910 "#endif\n"
911 "\n"
912 "#ifdef FRAGMENT_SHADER\n"
913 "uniform sampler2D Texture_Normal;\n"
914 "uniform sampler2D Texture_Refraction;\n"
915 "uniform sampler2D Texture_Reflection;\n"
916 "\n"
917 "uniform vec4 DistortScaleRefractReflect;\n"
918 "uniform vec4 ScreenScaleRefractReflect;\n"
919 "uniform vec4 ScreenCenterRefractReflect;\n"
920 "uniform vec4 RefractColor;\n"
921 "uniform vec4 ReflectColor;\n"
922 "uniform float ReflectFactor;\n"
923 "uniform float ReflectOffset;\n"
924 "\n"
925 "void main(void)\n"
926 "{\n"
927 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
928 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
929 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
930 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
931 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
932 "       // FIXME temporary hack to detect the case that the reflection\n"
933 "       // gets blackened at edges due to leaving the area that contains actual\n"
934 "       // content.\n"
935 "       // Remove this 'ack once we have a better way to stop this thing from\n"
936 "       // 'appening.\n"
937 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
938 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
939 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
940 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
941 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
942 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
943 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
944 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
945 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
946 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
947 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
948 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
949 "}\n"
950 "#endif\n"
951 "#else // !MODE_WATER\n"
952 "\n"
953 "\n"
954 "\n"
955 "\n"
956 "// common definitions between vertex shader and fragment shader:\n"
957 "\n"
958 "varying vec2 TexCoord;\n"
959 "#ifdef USEVERTEXTEXTUREBLEND\n"
960 "varying vec2 TexCoord2;\n"
961 "#endif\n"
962 "#ifdef USELIGHTMAP\n"
963 "varying vec2 TexCoordLightmap;\n"
964 "#endif\n"
965 "\n"
966 "#ifdef MODE_LIGHTSOURCE\n"
967 "varying vec3 CubeVector;\n"
968 "#endif\n"
969 "\n"
970 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
971 "varying vec3 LightVector;\n"
972 "#endif\n"
973 "\n"
974 "#ifdef USEEYEVECTOR\n"
975 "varying vec3 EyeVector;\n"
976 "#endif\n"
977 "#ifdef USEFOG\n"
978 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
979 "#endif\n"
980 "\n"
981 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
982 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
983 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
984 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
985 "#endif\n"
986 "\n"
987 "#ifdef USEREFLECTION\n"
988 "varying vec4 ModelViewProjectionPosition;\n"
989 "#endif\n"
990 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
991 "uniform vec3 LightPosition;\n"
992 "varying vec4 ModelViewPosition;\n"
993 "#endif\n"
994 "\n"
995 "#ifdef MODE_LIGHTSOURCE\n"
996 "uniform vec3 LightPosition;\n"
997 "#endif\n"
998 "uniform vec3 EyePosition;\n"
999 "#ifdef MODE_LIGHTDIRECTION\n"
1000 "uniform vec3 LightDir;\n"
1001 "#endif\n"
1002 "uniform vec4 FogPlane;\n"
1003 "\n"
1004 "#ifdef USESHADOWMAPORTHO\n"
1005 "varying vec3 ShadowMapTC;\n"
1006 "#endif\n"
1007 "\n"
1008 "\n"
1009 "\n"
1010 "\n"
1011 "\n"
1012 "// 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"
1013 "\n"
1014 "// fragment shader specific:\n"
1015 "#ifdef FRAGMENT_SHADER\n"
1016 "\n"
1017 "uniform sampler2D Texture_Normal;\n"
1018 "uniform sampler2D Texture_Color;\n"
1019 "uniform sampler2D Texture_Gloss;\n"
1020 "#ifdef USEGLOW\n"
1021 "uniform sampler2D Texture_Glow;\n"
1022 "#endif\n"
1023 "#ifdef USEVERTEXTEXTUREBLEND\n"
1024 "uniform sampler2D Texture_SecondaryNormal;\n"
1025 "uniform sampler2D Texture_SecondaryColor;\n"
1026 "uniform sampler2D Texture_SecondaryGloss;\n"
1027 "#ifdef USEGLOW\n"
1028 "uniform sampler2D Texture_SecondaryGlow;\n"
1029 "#endif\n"
1030 "#endif\n"
1031 "#ifdef USECOLORMAPPING\n"
1032 "uniform sampler2D Texture_Pants;\n"
1033 "uniform sampler2D Texture_Shirt;\n"
1034 "#endif\n"
1035 "#ifdef USEFOG\n"
1036 "#ifdef USEFOGHEIGHTTEXTURE\n"
1037 "uniform sampler2D Texture_FogHeightTexture;\n"
1038 "#endif\n"
1039 "uniform sampler2D Texture_FogMask;\n"
1040 "#endif\n"
1041 "#ifdef USELIGHTMAP\n"
1042 "uniform sampler2D Texture_Lightmap;\n"
1043 "#endif\n"
1044 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1045 "uniform sampler2D Texture_Deluxemap;\n"
1046 "#endif\n"
1047 "#ifdef USEREFLECTION\n"
1048 "uniform sampler2D Texture_Reflection;\n"
1049 "#endif\n"
1050 "\n"
1051 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1052 "uniform sampler2D Texture_ScreenDepth;\n"
1053 "uniform sampler2D Texture_ScreenNormalMap;\n"
1054 "#endif\n"
1055 "#ifdef USEDEFERREDLIGHTMAP\n"
1056 "uniform sampler2D Texture_ScreenDiffuse;\n"
1057 "uniform sampler2D Texture_ScreenSpecular;\n"
1058 "#endif\n"
1059 "\n"
1060 "uniform myhalf3 Color_Pants;\n"
1061 "uniform myhalf3 Color_Shirt;\n"
1062 "uniform myhalf3 FogColor;\n"
1063 "\n"
1064 "#ifdef USEFOG\n"
1065 "uniform float FogRangeRecip;\n"
1066 "uniform float FogPlaneViewDist;\n"
1067 "uniform float FogHeightFade;\n"
1068 "vec3 FogVertex(vec3 surfacecolor)\n"
1069 "{\n"
1070 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1071 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1072 "       float fogfrac;\n"
1073 "#ifdef USEFOGHEIGHTTEXTURE\n"
1074 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1075 "       fogfrac = fogheightpixel.a;\n"
1076 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1077 "#else\n"
1078 "# ifdef USEFOGOUTSIDE\n"
1079 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1080 "# else\n"
1081 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1082 "# endif\n"
1083 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1084 "#endif\n"
1085 "}\n"
1086 "#endif\n"
1087 "\n"
1088 "#ifdef USEOFFSETMAPPING\n"
1089 "uniform float OffsetMapping_Scale;\n"
1090 "vec2 OffsetMapping(vec2 TexCoord)\n"
1091 "{\n"
1092 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1093 "       // 14 sample relief mapping: linear search and then binary search\n"
1094 "       // this basically steps forward a small amount repeatedly until it finds\n"
1095 "       // itself inside solid, then jitters forward and back using decreasing\n"
1096 "       // amounts to find the impact\n"
1097 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1098 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1099 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1100 "       vec3 RT = vec3(TexCoord, 1);\n"
1101 "       OffsetVector *= 0.1;\n"
1102 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1103 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1104 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1105 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1106 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1107 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1108 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1109 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1110 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1111 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1112 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1113 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1114 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1115 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1116 "       return RT.xy;\n"
1117 "#else\n"
1118 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1119 "       // this basically moves forward the full distance, and then backs up based\n"
1120 "       // on height of samples\n"
1121 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1122 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1123 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1124 "       TexCoord += OffsetVector;\n"
1125 "       OffsetVector *= 0.333;\n"
1126 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1127 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1128 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1129 "       return TexCoord;\n"
1130 "#endif\n"
1131 "}\n"
1132 "#endif // USEOFFSETMAPPING\n"
1133 "\n"
1134 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1135 "uniform sampler2D Texture_Attenuation;\n"
1136 "uniform samplerCube Texture_Cube;\n"
1137 "#endif\n"
1138 "\n"
1139 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1140 "\n"
1141 "#ifdef USESHADOWMAPRECT\n"
1142 "# ifdef USESHADOWSAMPLER\n"
1143 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1144 "# else\n"
1145 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1146 "# endif\n"
1147 "#endif\n"
1148 "\n"
1149 "#ifdef USESHADOWMAP2D\n"
1150 "# ifdef USESHADOWSAMPLER\n"
1151 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1152 "# else\n"
1153 "uniform sampler2D Texture_ShadowMap2D;\n"
1154 "# endif\n"
1155 "#endif\n"
1156 "\n"
1157 "#ifdef USESHADOWMAPVSDCT\n"
1158 "uniform samplerCube Texture_CubeProjection;\n"
1159 "#endif\n"
1160 "\n"
1161 "#ifdef USESHADOWMAPCUBE\n"
1162 "# ifdef USESHADOWSAMPLER\n"
1163 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1164 "# else\n"
1165 "uniform samplerCube Texture_ShadowMapCube;\n"
1166 "# endif\n"
1167 "#endif\n"
1168 "\n"
1169 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1170 "uniform vec2 ShadowMap_TextureScale;\n"
1171 "uniform vec4 ShadowMap_Parameters;\n"
1172 "#endif\n"
1173 "\n"
1174 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1175 "# ifdef USESHADOWMAPORTHO\n"
1176 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1177 "# else\n"
1178 "#  ifdef USESHADOWMAPVSDCT\n"
1179 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1180 "{\n"
1181 "       vec3 adir = abs(dir);\n"
1182 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1183 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1184 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1185 "}\n"
1186 "#  else\n"
1187 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1188 "{\n"
1189 "       vec3 adir = abs(dir);\n"
1190 "       float ma = adir.z;\n"
1191 "       vec4 proj = vec4(dir, 2.5);\n"
1192 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1193 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1194 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1195 "       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"
1196 "}\n"
1197 "#  endif\n"
1198 "# endif\n"
1199 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1200 "\n"
1201 "#ifdef USESHADOWMAPCUBE\n"
1202 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1203 "{\n"
1204 "       vec3 adir = abs(dir);\n"
1205 "       return vec4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
1206 "}\n"
1207 "#endif\n"
1208 "\n"
1209 "# ifdef USESHADOWMAPRECT\n"
1210 "float ShadowMapCompare(vec3 dir)\n"
1211 "{\n"
1212 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1213 "       float f;\n"
1214 "#  ifdef USESHADOWSAMPLER\n"
1215 "\n"
1216 "#    ifdef USESHADOWMAPPCF\n"
1217 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1218 "       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"
1219 "#    else\n"
1220 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1221 "#    endif\n"
1222 "\n"
1223 "#  else\n"
1224 "\n"
1225 "#    ifdef USESHADOWMAPPCF\n"
1226 "#      if USESHADOWMAPPCF > 1\n"
1227 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1228 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1229 "       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"
1230 "       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"
1231 "       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"
1232 "       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"
1233 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1234 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1235 "#      else\n"
1236 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1237 "       vec2 offset = fract(shadowmaptc.xy);\n"
1238 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1239 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1240 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1241 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1242 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1243 "#      endif\n"
1244 "#    else\n"
1245 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1246 "#    endif\n"
1247 "\n"
1248 "#  endif\n"
1249 "#  ifdef USESHADOWMAPORTHO\n"
1250 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1251 "#  else\n"
1252 "       return f;\n"
1253 "#  endif\n"
1254 "}\n"
1255 "# endif\n"
1256 "\n"
1257 "# ifdef USESHADOWMAP2D\n"
1258 "float ShadowMapCompare(vec3 dir)\n"
1259 "{\n"
1260 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1261 "       float f;\n"
1262 "\n"
1263 "#  ifdef USESHADOWSAMPLER\n"
1264 "#    ifdef USESHADOWMAPPCF\n"
1265 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1266 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1267 "       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"
1268 "#    else\n"
1269 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1270 "#    endif\n"
1271 "#  else\n"
1272 "#    ifdef USESHADOWMAPPCF\n"
1273 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1274 "#      ifdef GL_ARB_texture_gather\n"
1275 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1276 "#      else\n"
1277 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1278 "#      endif\n"
1279 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1280 "#      if USESHADOWMAPPCF > 1\n"
1281 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1282 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1283 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1284 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1285 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1286 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1287 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1288 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1289 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1290 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1291 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1292 "       locols.yz += group2.ab;\n"
1293 "       hicols.yz += group8.rg;\n"
1294 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1295 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1296 "                               mix(locols, hicols, offset.y);\n"
1297 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1298 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1299 "       f = dot(cols, vec4(1.0/25.0));\n"
1300 "#      else\n"
1301 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1302 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1303 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1304 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1305 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1306 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1307 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1308 "#      endif\n"
1309 "#     else\n"
1310 "#      ifdef GL_EXT_gpu_shader4\n"
1311 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1312 "#      else\n"
1313 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1314 "#      endif\n"
1315 "#      if USESHADOWMAPPCF > 1\n"
1316 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1317 "       center *= ShadowMap_TextureScale;\n"
1318 "       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"
1319 "       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"
1320 "       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"
1321 "       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"
1322 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1323 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1324 "#      else\n"
1325 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1326 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1327 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1328 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1329 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1330 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1331 "#      endif\n"
1332 "#     endif\n"
1333 "#    else\n"
1334 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1335 "#    endif\n"
1336 "#  endif\n"
1337 "#  ifdef USESHADOWMAPORTHO\n"
1338 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1339 "#  else\n"
1340 "       return f;\n"
1341 "#  endif\n"
1342 "}\n"
1343 "# endif\n"
1344 "\n"
1345 "# ifdef USESHADOWMAPCUBE\n"
1346 "float ShadowMapCompare(vec3 dir)\n"
1347 "{\n"
1348 "       // apply depth texture cubemap as light filter\n"
1349 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1350 "       float f;\n"
1351 "#  ifdef USESHADOWSAMPLER\n"
1352 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1353 "#  else\n"
1354 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1355 "#  endif\n"
1356 "       return f;\n"
1357 "}\n"
1358 "# endif\n"
1359 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1360 "#endif // FRAGMENT_SHADER\n"
1361 "\n"
1362 "\n"
1363 "\n"
1364 "\n"
1365 "#ifdef MODE_DEFERREDGEOMETRY\n"
1366 "#ifdef VERTEX_SHADER\n"
1367 "uniform mat4 TexMatrix;\n"
1368 "#ifdef USEVERTEXTEXTUREBLEND\n"
1369 "uniform mat4 BackgroundTexMatrix;\n"
1370 "#endif\n"
1371 "uniform mat4 ModelViewMatrix;\n"
1372 "void main(void)\n"
1373 "{\n"
1374 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1375 "#ifdef USEVERTEXTEXTUREBLEND\n"
1376 "       gl_FrontColor = gl_Color;\n"
1377 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1378 "#endif\n"
1379 "\n"
1380 "       // transform unnormalized eye direction into tangent space\n"
1381 "#ifdef USEOFFSETMAPPING\n"
1382 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1383 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1384 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1385 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1386 "#endif\n"
1387 "\n"
1388 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1389 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1390 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1391 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1392 "}\n"
1393 "#endif // VERTEX_SHADER\n"
1394 "\n"
1395 "#ifdef FRAGMENT_SHADER\n"
1396 "void main(void)\n"
1397 "{\n"
1398 "#ifdef USEOFFSETMAPPING\n"
1399 "       // apply offsetmapping\n"
1400 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1401 "#define TexCoord TexCoordOffset\n"
1402 "#endif\n"
1403 "\n"
1404 "#ifdef USEALPHAKILL\n"
1405 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1406 "               discard;\n"
1407 "#endif\n"
1408 "\n"
1409 "#ifdef USEVERTEXTEXTUREBLEND\n"
1410 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1411 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1412 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1413 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1414 "#endif\n"
1415 "\n"
1416 "#ifdef USEVERTEXTEXTUREBLEND\n"
1417 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1418 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1419 "#else\n"
1420 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1421 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1422 "#endif\n"
1423 "\n"
1424 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1425 "}\n"
1426 "#endif // FRAGMENT_SHADER\n"
1427 "#else // !MODE_DEFERREDGEOMETRY\n"
1428 "\n"
1429 "\n"
1430 "\n"
1431 "\n"
1432 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1433 "#ifdef VERTEX_SHADER\n"
1434 "uniform mat4 ModelViewMatrix;\n"
1435 "void main(void)\n"
1436 "{\n"
1437 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1438 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1439 "}\n"
1440 "#endif // VERTEX_SHADER\n"
1441 "\n"
1442 "#ifdef FRAGMENT_SHADER\n"
1443 "uniform mat4 ViewToLight;\n"
1444 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1445 "uniform vec2 ScreenToDepth;\n"
1446 "uniform myhalf3 DeferredColor_Ambient;\n"
1447 "uniform myhalf3 DeferredColor_Diffuse;\n"
1448 "#ifdef USESPECULAR\n"
1449 "uniform myhalf3 DeferredColor_Specular;\n"
1450 "uniform myhalf SpecularPower;\n"
1451 "#endif\n"
1452 "uniform myhalf2 PixelToScreenTexCoord;\n"
1453 "void main(void)\n"
1454 "{\n"
1455 "       // calculate viewspace pixel position\n"
1456 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1457 "       vec3 position;\n"
1458 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1459 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1460 "       // decode viewspace pixel normal\n"
1461 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1462 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1463 "       // surfacenormal = pixel normal in viewspace\n"
1464 "       // LightVector = pixel to light in viewspace\n"
1465 "       // CubeVector = position in lightspace\n"
1466 "       // eyevector = pixel to view in viewspace\n"
1467 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1468 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1469 "#ifdef USEDIFFUSE\n"
1470 "       // calculate diffuse shading\n"
1471 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1472 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1473 "#endif\n"
1474 "#ifdef USESPECULAR\n"
1475 "       // calculate directional shading\n"
1476 "       vec3 eyevector = position * -1.0;\n"
1477 "#  ifdef USEEXACTSPECULARMATH\n"
1478 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1479 "#  else\n"
1480 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1481 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1482 "#  endif\n"
1483 "#endif\n"
1484 "\n"
1485 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1486 "       fade *= ShadowMapCompare(CubeVector);\n"
1487 "#endif\n"
1488 "\n"
1489 "#ifdef USEDIFFUSE\n"
1490 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1491 "#else\n"
1492 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1493 "#endif\n"
1494 "#ifdef USESPECULAR\n"
1495 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1496 "#else\n"
1497 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1498 "#endif\n"
1499 "\n"
1500 "# ifdef USECUBEFILTER\n"
1501 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1502 "       gl_FragData[0].rgb *= cubecolor;\n"
1503 "       gl_FragData[1].rgb *= cubecolor;\n"
1504 "# endif\n"
1505 "}\n"
1506 "#endif // FRAGMENT_SHADER\n"
1507 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1508 "\n"
1509 "\n"
1510 "\n"
1511 "\n"
1512 "#ifdef VERTEX_SHADER\n"
1513 "uniform mat4 TexMatrix;\n"
1514 "#ifdef USEVERTEXTEXTUREBLEND\n"
1515 "uniform mat4 BackgroundTexMatrix;\n"
1516 "#endif\n"
1517 "#ifdef MODE_LIGHTSOURCE\n"
1518 "uniform mat4 ModelToLight;\n"
1519 "#endif\n"
1520 "#ifdef USESHADOWMAPORTHO\n"
1521 "uniform mat4 ShadowMapMatrix;\n"
1522 "#endif\n"
1523 "void main(void)\n"
1524 "{\n"
1525 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1526 "       gl_FrontColor = gl_Color;\n"
1527 "#endif\n"
1528 "       // copy the surface texcoord\n"
1529 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1530 "#ifdef USEVERTEXTEXTUREBLEND\n"
1531 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1532 "#endif\n"
1533 "#ifdef USELIGHTMAP\n"
1534 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1535 "#endif\n"
1536 "\n"
1537 "#ifdef MODE_LIGHTSOURCE\n"
1538 "       // transform vertex position into light attenuation/cubemap space\n"
1539 "       // (-1 to +1 across the light box)\n"
1540 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1541 "\n"
1542 "# ifdef USEDIFFUSE\n"
1543 "       // transform unnormalized light direction into tangent space\n"
1544 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1545 "       //  normalize it per pixel)\n"
1546 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1547 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1548 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1549 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1550 "# endif\n"
1551 "#endif\n"
1552 "\n"
1553 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1554 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1555 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1556 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1557 "#endif\n"
1558 "\n"
1559 "       // transform unnormalized eye direction into tangent space\n"
1560 "#ifdef USEEYEVECTOR\n"
1561 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1562 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1563 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1564 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1565 "#endif\n"
1566 "\n"
1567 "#ifdef USEFOG\n"
1568 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1569 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1570 "#endif\n"
1571 "\n"
1572 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1573 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1574 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1575 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1576 "#endif\n"
1577 "\n"
1578 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1579 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1580 "\n"
1581 "#ifdef USESHADOWMAPORTHO\n"
1582 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1583 "#endif\n"
1584 "\n"
1585 "#ifdef USEREFLECTION\n"
1586 "       ModelViewProjectionPosition = gl_Position;\n"
1587 "#endif\n"
1588 "}\n"
1589 "#endif // VERTEX_SHADER\n"
1590 "\n"
1591 "\n"
1592 "\n"
1593 "\n"
1594 "#ifdef FRAGMENT_SHADER\n"
1595 "#ifdef USEDEFERREDLIGHTMAP\n"
1596 "uniform myhalf2 PixelToScreenTexCoord;\n"
1597 "uniform myhalf3 DeferredMod_Diffuse;\n"
1598 "uniform myhalf3 DeferredMod_Specular;\n"
1599 "#endif\n"
1600 "uniform myhalf3 Color_Ambient;\n"
1601 "uniform myhalf3 Color_Diffuse;\n"
1602 "uniform myhalf3 Color_Specular;\n"
1603 "uniform myhalf SpecularPower;\n"
1604 "#ifdef USEGLOW\n"
1605 "uniform myhalf3 Color_Glow;\n"
1606 "#endif\n"
1607 "uniform myhalf Alpha;\n"
1608 "#ifdef USEREFLECTION\n"
1609 "uniform vec4 DistortScaleRefractReflect;\n"
1610 "uniform vec4 ScreenScaleRefractReflect;\n"
1611 "uniform vec4 ScreenCenterRefractReflect;\n"
1612 "uniform myhalf4 ReflectColor;\n"
1613 "#endif\n"
1614 "#ifdef USEREFLECTCUBE\n"
1615 "uniform mat4 ModelToReflectCube;\n"
1616 "uniform sampler2D Texture_ReflectMask;\n"
1617 "uniform samplerCube Texture_ReflectCube;\n"
1618 "#endif\n"
1619 "#ifdef MODE_LIGHTDIRECTION\n"
1620 "uniform myhalf3 LightColor;\n"
1621 "#endif\n"
1622 "#ifdef MODE_LIGHTSOURCE\n"
1623 "uniform myhalf3 LightColor;\n"
1624 "#endif\n"
1625 "void main(void)\n"
1626 "{\n"
1627 "#ifdef USEOFFSETMAPPING\n"
1628 "       // apply offsetmapping\n"
1629 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1630 "#define TexCoord TexCoordOffset\n"
1631 "#endif\n"
1632 "\n"
1633 "       // combine the diffuse textures (base, pants, shirt)\n"
1634 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1635 "#ifdef USEALPHAKILL\n"
1636 "       if (color.a < 0.5)\n"
1637 "               discard;\n"
1638 "#endif\n"
1639 "       color.a *= Alpha;\n"
1640 "#ifdef USECOLORMAPPING\n"
1641 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1642 "#endif\n"
1643 "#ifdef USEVERTEXTEXTUREBLEND\n"
1644 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1645 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1646 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1647 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1648 "       color.a = 1.0;\n"
1649 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1650 "#endif\n"
1651 "\n"
1652 "       // get the surface normal\n"
1653 "#ifdef USEVERTEXTEXTUREBLEND\n"
1654 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1655 "#else\n"
1656 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1657 "#endif\n"
1658 "\n"
1659 "       // get the material colors\n"
1660 "       myhalf3 diffusetex = color.rgb;\n"
1661 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1662 "# ifdef USEVERTEXTEXTUREBLEND\n"
1663 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1664 "# else\n"
1665 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1666 "# endif\n"
1667 "#endif\n"
1668 "\n"
1669 "#ifdef USEREFLECTCUBE\n"
1670 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1671 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1672 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1673 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1674 "#endif\n"
1675 "\n"
1676 "\n"
1677 "\n"
1678 "\n"
1679 "#ifdef MODE_LIGHTSOURCE\n"
1680 "       // light source\n"
1681 "#ifdef USEDIFFUSE\n"
1682 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1683 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1684 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1685 "#ifdef USESPECULAR\n"
1686 "#ifdef USEEXACTSPECULARMATH\n"
1687 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1688 "#else\n"
1689 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1690 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1691 "#endif\n"
1692 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1693 "#endif\n"
1694 "#else\n"
1695 "       color.rgb = diffusetex * Color_Ambient;\n"
1696 "#endif\n"
1697 "       color.rgb *= LightColor;\n"
1698 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1699 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1700 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1701 "#endif\n"
1702 "# ifdef USECUBEFILTER\n"
1703 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1704 "# endif\n"
1705 "#endif // MODE_LIGHTSOURCE\n"
1706 "\n"
1707 "\n"
1708 "\n"
1709 "\n"
1710 "#ifdef MODE_LIGHTDIRECTION\n"
1711 "#define SHADING\n"
1712 "#ifdef USEDIFFUSE\n"
1713 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1714 "#endif\n"
1715 "#define lightcolor LightColor\n"
1716 "#endif // MODE_LIGHTDIRECTION\n"
1717 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1718 "#define SHADING\n"
1719 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1720 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1721 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1722 "       // convert modelspace light vector to tangentspace\n"
1723 "       myhalf3 lightnormal;\n"
1724 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1725 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1726 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1727 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1728 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1729 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1730 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1731 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1732 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1733 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1734 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1735 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1736 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1737 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1738 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1739 "#define SHADING\n"
1740 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1741 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1742 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1743 "#endif\n"
1744 "\n"
1745 "\n"
1746 "\n"
1747 "\n"
1748 "#ifdef MODE_LIGHTMAP\n"
1749 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1750 "#endif // MODE_LIGHTMAP\n"
1751 "#ifdef MODE_VERTEXCOLOR\n"
1752 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1753 "#endif // MODE_VERTEXCOLOR\n"
1754 "#ifdef MODE_FLATCOLOR\n"
1755 "       color.rgb = diffusetex * Color_Ambient;\n"
1756 "#endif // MODE_FLATCOLOR\n"
1757 "\n"
1758 "\n"
1759 "\n"
1760 "\n"
1761 "#ifdef SHADING\n"
1762 "# ifdef USEDIFFUSE\n"
1763 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1764 "#  ifdef USESPECULAR\n"
1765 "#   ifdef USEEXACTSPECULARMATH\n"
1766 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1767 "#   else\n"
1768 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1769 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1770 "#   endif\n"
1771 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1772 "#  else\n"
1773 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1774 "#  endif\n"
1775 "# else\n"
1776 "       color.rgb = diffusetex * Color_Ambient;\n"
1777 "# endif\n"
1778 "#endif\n"
1779 "\n"
1780 "#ifdef USESHADOWMAPORTHO\n"
1781 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1782 "#endif\n"
1783 "\n"
1784 "#ifdef USEDEFERREDLIGHTMAP\n"
1785 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1786 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1787 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1788 "#endif\n"
1789 "\n"
1790 "#ifdef USEGLOW\n"
1791 "#ifdef USEVERTEXTEXTUREBLEND\n"
1792 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1793 "#else\n"
1794 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1795 "#endif\n"
1796 "#endif\n"
1797 "\n"
1798 "#ifdef USEFOG\n"
1799 "       color.rgb = FogVertex(color.rgb);\n"
1800 "#endif\n"
1801 "\n"
1802 "       // 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"
1803 "#ifdef USEREFLECTION\n"
1804 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1805 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1806 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1807 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1808 "       // FIXME temporary hack to detect the case that the reflection\n"
1809 "       // gets blackened at edges due to leaving the area that contains actual\n"
1810 "       // content.\n"
1811 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1812 "       // 'appening.\n"
1813 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1814 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1815 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1816 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1817 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1818 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1819 "#endif\n"
1820 "\n"
1821 "       gl_FragColor = vec4(color);\n"
1822 "}\n"
1823 "#endif // FRAGMENT_SHADER\n"
1824 "\n"
1825 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1826 "#endif // !MODE_DEFERREDGEOMETRY\n"
1827 "#endif // !MODE_WATER\n"
1828 "#endif // !MODE_REFRACTION\n"
1829 "#endif // !MODE_BLOOMBLUR\n"
1830 "#endif // !MODE_GENERIC\n"
1831 "#endif // !MODE_POSTPROCESS\n"
1832 "#endif // !MODE_SHOWDEPTH\n"
1833 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1834 ;
1835
1836 /*
1837 =========================================================================================================================================================
1838
1839
1840
1841 =========================================================================================================================================================
1842
1843
1844
1845 =========================================================================================================================================================
1846
1847
1848
1849 =========================================================================================================================================================
1850
1851
1852
1853 =========================================================================================================================================================
1854
1855
1856
1857 =========================================================================================================================================================
1858
1859
1860
1861 =========================================================================================================================================================
1862 */
1863
1864 const char *builtincgshaderstring =
1865 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1866 "// written by Forest 'LordHavoc' Hale\n"
1867 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1868 "\n"
1869 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1870 "#if defined(USEREFLECTION)\n"
1871 "#undef USESHADOWMAPORTHO\n"
1872 "#endif\n"
1873 "\n"
1874 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1875 "# define USEFOG\n"
1876 "#endif\n"
1877 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1878 "#define USELIGHTMAP\n"
1879 "#endif\n"
1880 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1881 "#define USEEYEVECTOR\n"
1882 "#endif\n"
1883 "\n"
1884 "#ifdef FRAGMENT_SHADER\n"
1885 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1886 "#endif\n"
1887 "\n"
1888 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1889 "#ifdef VERTEX_SHADER\n"
1890 "void main\n"
1891 "(\n"
1892 "float4 gl_Vertex : POSITION,\n"
1893 "uniform float4x4 ModelViewProjectionMatrix,\n"
1894 "out float4 gl_Position : POSITION\n"
1895 ")\n"
1896 "{\n"
1897 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1898 "}\n"
1899 "#endif\n"
1900 "#else // !MODE_DEPTH_ORSHADOW\n"
1901 "\n"
1902 "\n"
1903 "\n"
1904 "\n"
1905 "#ifdef MODE_SHOWDEPTH\n"
1906 "#ifdef VERTEX_SHADER\n"
1907 "void main\n"
1908 "(\n"
1909 "float4 gl_Vertex : POSITION,\n"
1910 "uniform float4x4 ModelViewProjectionMatrix,\n"
1911 "out float4 gl_Position : POSITION,\n"
1912 "out float4 gl_FrontColor : COLOR0\n"
1913 ")\n"
1914 "{\n"
1915 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1916 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1917 "}\n"
1918 "#endif\n"
1919 "\n"
1920 "#ifdef FRAGMENT_SHADER\n"
1921 "void main\n"
1922 "(\n"
1923 "float4 gl_FrontColor : COLOR0,\n"
1924 "out float4 gl_FragColor : COLOR\n"
1925 ")\n"
1926 "{\n"
1927 "       gl_FragColor = gl_FrontColor;\n"
1928 "}\n"
1929 "#endif\n"
1930 "#else // !MODE_SHOWDEPTH\n"
1931 "\n"
1932 "\n"
1933 "\n"
1934 "\n"
1935 "#ifdef MODE_POSTPROCESS\n"
1936 "\n"
1937 "#ifdef VERTEX_SHADER\n"
1938 "void main\n"
1939 "(\n"
1940 "float4 gl_Vertex : POSITION,\n"
1941 "uniform float4x4 ModelViewProjectionMatrix,\n"
1942 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1943 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1944 "out float4 gl_Position : POSITION,\n"
1945 "out float2 TexCoord1 : TEXCOORD0,\n"
1946 "out float2 TexCoord2 : TEXCOORD1\n"
1947 ")\n"
1948 "{\n"
1949 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1950 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1951 "#ifdef USEBLOOM\n"
1952 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1953 "#endif\n"
1954 "}\n"
1955 "#endif\n"
1956 "\n"
1957 "#ifdef FRAGMENT_SHADER\n"
1958 "void main\n"
1959 "(\n"
1960 "float2 TexCoord1 : TEXCOORD0,\n"
1961 "float2 TexCoord2 : TEXCOORD1,\n"
1962 "uniform sampler2D Texture_First,\n"
1963 "#ifdef USEBLOOM\n"
1964 "uniform sampler2D Texture_Second,\n"
1965 "#endif\n"
1966 "#ifdef USEGAMMARAMPS\n"
1967 "uniform sampler2D Texture_GammaRamps,\n"
1968 "#endif\n"
1969 "#ifdef USESATURATION\n"
1970 "uniform float Saturation,\n"
1971 "#endif\n"
1972 "#ifdef USEVIEWTINT\n"
1973 "uniform float4 ViewTintColor,\n"
1974 "#endif\n"
1975 "uniform float4 UserVec1,\n"
1976 "uniform float4 UserVec2,\n"
1977 "uniform float4 UserVec3,\n"
1978 "uniform float4 UserVec4,\n"
1979 "uniform float ClientTime,\n"
1980 "uniform float2 PixelSize,\n"
1981 "out float4 gl_FragColor : COLOR\n"
1982 ")\n"
1983 "{\n"
1984 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1985 "#ifdef USEBLOOM\n"
1986 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1987 "#endif\n"
1988 "#ifdef USEVIEWTINT\n"
1989 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1990 "#endif\n"
1991 "\n"
1992 "#ifdef USEPOSTPROCESSING\n"
1993 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1994 "// 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"
1995 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1996 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1997 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1998 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1999 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2000 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
2001 "#endif\n"
2002 "\n"
2003 "#ifdef USESATURATION\n"
2004 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2005 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2006 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2007 "       gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
2008 "#endif\n"
2009 "\n"
2010 "#ifdef USEGAMMARAMPS\n"
2011 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2012 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2013 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2014 "#endif\n"
2015 "}\n"
2016 "#endif\n"
2017 "#else // !MODE_POSTPROCESS\n"
2018 "\n"
2019 "\n"
2020 "\n"
2021 "\n"
2022 "#ifdef MODE_GENERIC\n"
2023 "#ifdef VERTEX_SHADER\n"
2024 "void main\n"
2025 "(\n"
2026 "float4 gl_Vertex : POSITION,\n"
2027 "uniform float4x4 ModelViewProjectionMatrix,\n"
2028 "float4 gl_Color : COLOR0,\n"
2029 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2030 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2031 "out float4 gl_Position : POSITION,\n"
2032 "out float4 gl_FrontColor : COLOR,\n"
2033 "out float2 TexCoord1 : TEXCOORD0,\n"
2034 "out float2 TexCoord2 : TEXCOORD1\n"
2035 ")\n"
2036 "{\n"
2037 "       gl_FrontColor = gl_Color;\n"
2038 "#ifdef USEDIFFUSE\n"
2039 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2040 "#endif\n"
2041 "#ifdef USESPECULAR\n"
2042 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2043 "#endif\n"
2044 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2045 "}\n"
2046 "#endif\n"
2047 "\n"
2048 "#ifdef FRAGMENT_SHADER\n"
2049 "\n"
2050 "void main\n"
2051 "(\n"
2052 "float4 gl_FrontColor : COLOR,\n"
2053 "float2 TexCoord1 : TEXCOORD0,\n"
2054 "float2 TexCoord2 : TEXCOORD1,\n"
2055 "#ifdef USEDIFFUSE\n"
2056 "uniform sampler2D Texture_First,\n"
2057 "#endif\n"
2058 "#ifdef USESPECULAR\n"
2059 "uniform sampler2D Texture_Second,\n"
2060 "#endif\n"
2061 "out float4 gl_FragColor : COLOR\n"
2062 ")\n"
2063 "{\n"
2064 "       gl_FragColor = gl_FrontColor;\n"
2065 "#ifdef USEDIFFUSE\n"
2066 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2067 "#endif\n"
2068 "\n"
2069 "#ifdef USESPECULAR\n"
2070 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2071 "# ifdef USECOLORMAPPING\n"
2072 "       gl_FragColor *= tex2;\n"
2073 "# endif\n"
2074 "# ifdef USEGLOW\n"
2075 "       gl_FragColor += tex2;\n"
2076 "# endif\n"
2077 "# ifdef USEVERTEXTEXTUREBLEND\n"
2078 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2079 "# endif\n"
2080 "#endif\n"
2081 "}\n"
2082 "#endif\n"
2083 "#else // !MODE_GENERIC\n"
2084 "\n"
2085 "\n"
2086 "\n"
2087 "\n"
2088 "#ifdef MODE_BLOOMBLUR\n"
2089 "#ifdef VERTEX_SHADER\n"
2090 "void main\n"
2091 "(\n"
2092 "float4 gl_Vertex : POSITION,\n"
2093 "uniform float4x4 ModelViewProjectionMatrix,\n"
2094 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2095 "out float4 gl_Position : POSITION,\n"
2096 "out float2 TexCoord : TEXCOORD0\n"
2097 ")\n"
2098 "{\n"
2099 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2100 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2101 "}\n"
2102 "#endif\n"
2103 "\n"
2104 "#ifdef FRAGMENT_SHADER\n"
2105 "\n"
2106 "void main\n"
2107 "(\n"
2108 "float2 TexCoord : TEXCOORD0,\n"
2109 "uniform sampler2D Texture_First,\n"
2110 "uniform float4 BloomBlur_Parameters,\n"
2111 "out float4 gl_FragColor : COLOR\n"
2112 ")\n"
2113 "{\n"
2114 "       int i;\n"
2115 "       float2 tc = TexCoord;\n"
2116 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2117 "       tc += BloomBlur_Parameters.xy;\n"
2118 "       for (i = 1;i < SAMPLES;i++)\n"
2119 "       {\n"
2120 "               color += tex2D(Texture_First, tc).rgb;\n"
2121 "               tc += BloomBlur_Parameters.xy;\n"
2122 "       }\n"
2123 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2124 "}\n"
2125 "#endif\n"
2126 "#else // !MODE_BLOOMBLUR\n"
2127 "#ifdef MODE_REFRACTION\n"
2128 "#ifdef VERTEX_SHADER\n"
2129 "void main\n"
2130 "(\n"
2131 "float4 gl_Vertex : POSITION,\n"
2132 "uniform float4x4 ModelViewProjectionMatrix,\n"
2133 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2134 "uniform float4x4 TexMatrix,\n"
2135 "uniform float3 EyePosition,\n"
2136 "out float4 gl_Position : POSITION,\n"
2137 "out float2 TexCoord : TEXCOORD0,\n"
2138 "out float3 EyeVector : TEXCOORD1,\n"
2139 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2140 ")\n"
2141 "{\n"
2142 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2143 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2144 "       ModelViewProjectionPosition = gl_Position;\n"
2145 "}\n"
2146 "#endif\n"
2147 "\n"
2148 "#ifdef FRAGMENT_SHADER\n"
2149 "void main\n"
2150 "(\n"
2151 "float2 TexCoord : TEXCOORD0,\n"
2152 "float3 EyeVector : TEXCOORD1,\n"
2153 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2154 "uniform sampler2D Texture_Normal,\n"
2155 "uniform sampler2D Texture_Refraction,\n"
2156 "uniform sampler2D Texture_Reflection,\n"
2157 "uniform float4 DistortScaleRefractReflect,\n"
2158 "uniform float4 ScreenScaleRefractReflect,\n"
2159 "uniform float4 ScreenCenterRefractReflect,\n"
2160 "uniform float4 RefractColor,\n"
2161 "out float4 gl_FragColor : COLOR\n"
2162 ")\n"
2163 "{\n"
2164 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2165 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2166 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2167 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2168 "       // FIXME temporary hack to detect the case that the reflection\n"
2169 "       // gets blackened at edges due to leaving the area that contains actual\n"
2170 "       // content.\n"
2171 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2172 "       // 'appening.\n"
2173 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2174 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2175 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2176 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2177 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2178 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2179 "}\n"
2180 "#endif\n"
2181 "#else // !MODE_REFRACTION\n"
2182 "\n"
2183 "\n"
2184 "\n"
2185 "\n"
2186 "#ifdef MODE_WATER\n"
2187 "#ifdef VERTEX_SHADER\n"
2188 "\n"
2189 "void main\n"
2190 "(\n"
2191 "float4 gl_Vertex : POSITION,\n"
2192 "uniform float4x4 ModelViewProjectionMatrix,\n"
2193 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2194 "uniform float4x4 TexMatrix,\n"
2195 "uniform float3 EyePosition,\n"
2196 "out float4 gl_Position : POSITION,\n"
2197 "out float2 TexCoord : TEXCOORD0,\n"
2198 "out float3 EyeVector : TEXCOORD1,\n"
2199 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2200 ")\n"
2201 "{\n"
2202 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2203 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2204 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2205 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2206 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2207 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2208 "       ModelViewProjectionPosition = gl_Position;\n"
2209 "}\n"
2210 "#endif\n"
2211 "\n"
2212 "#ifdef FRAGMENT_SHADER\n"
2213 "void main\n"
2214 "(\n"
2215 "float2 TexCoord : TEXCOORD0,\n"
2216 "float3 EyeVector : TEXCOORD1,\n"
2217 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2218 "uniform sampler2D Texture_Normal,\n"
2219 "uniform sampler2D Texture_Refraction,\n"
2220 "uniform sampler2D Texture_Reflection,\n"
2221 "uniform float4 DistortScaleRefractReflect,\n"
2222 "uniform float4 ScreenScaleRefractReflect,\n"
2223 "uniform float4 ScreenCenterRefractReflect,\n"
2224 "uniform float4 RefractColor,\n"
2225 "uniform float4 ReflectColor,\n"
2226 "uniform float ReflectFactor,\n"
2227 "uniform float ReflectOffset,\n"
2228 "out float4 gl_FragColor : COLOR\n"
2229 ")\n"
2230 "{\n"
2231 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2232 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2233 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2234 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2235 "       // FIXME temporary hack to detect the case that the reflection\n"
2236 "       // gets blackened at edges due to leaving the area that contains actual\n"
2237 "       // content.\n"
2238 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2239 "       // 'appening.\n"
2240 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2241 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2242 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2243 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2244 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2245 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2246 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2247 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2248 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2249 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2250 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2251 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2252 "}\n"
2253 "#endif\n"
2254 "#else // !MODE_WATER\n"
2255 "\n"
2256 "\n"
2257 "\n"
2258 "\n"
2259 "// 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"
2260 "\n"
2261 "// fragment shader specific:\n"
2262 "#ifdef FRAGMENT_SHADER\n"
2263 "\n"
2264 "#ifdef USEFOG\n"
2265 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask, sampler2D Texture_FogHeightTexture)\n"
2266 "{\n"
2267 "       float fogfrac;\n"
2268 "#ifdef USEFOGHEIGHTTEXTURE\n"
2269 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2270 "       fogfrac = fogheightpixel.a;\n"
2271 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2272 "#else\n"
2273 "# ifdef USEFOGOUTSIDE\n"
2274 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2275 "# else\n"
2276 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2277 "# endif\n"
2278 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2279 "#endif\n"
2280 "}\n"
2281 "#endif\n"
2282 "\n"
2283 "#ifdef USEOFFSETMAPPING\n"
2284 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2285 "{\n"
2286 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2287 "       // 14 sample relief mapping: linear search and then binary search\n"
2288 "       // this basically steps forward a small amount repeatedly until it finds\n"
2289 "       // itself inside solid, then jitters forward and back using decreasing\n"
2290 "       // amounts to find the impact\n"
2291 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2292 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2293 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2294 "       float3 RT = float3(TexCoord, 1);\n"
2295 "       OffsetVector *= 0.1;\n"
2296 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2297 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2298 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2299 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2300 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2301 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2302 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2303 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2304 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2305 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2306 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2307 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2308 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2309 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2310 "       return RT.xy;\n"
2311 "#else\n"
2312 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2313 "       // this basically moves forward the full distance, and then backs up based\n"
2314 "       // on height of samples\n"
2315 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2316 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2317 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2318 "       TexCoord += OffsetVector;\n"
2319 "       OffsetVector *= 0.333;\n"
2320 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2321 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2322 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2323 "       return TexCoord;\n"
2324 "#endif\n"
2325 "}\n"
2326 "#endif // USEOFFSETMAPPING\n"
2327 "\n"
2328 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2329 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2330 "# ifdef USESHADOWMAPORTHO\n"
2331 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2332 "# else\n"
2333 "#  ifdef USESHADOWMAPVSDCT\n"
2334 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2335 "{\n"
2336 "       float3 adir = abs(dir);\n"
2337 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2338 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2339 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2340 "}\n"
2341 "#  else\n"
2342 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2343 "{\n"
2344 "       float3 adir = abs(dir);\n"
2345 "       float ma = adir.z;\n"
2346 "       float4 proj = float4(dir, 2.5);\n"
2347 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2348 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2349 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2350 "       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"
2351 "}\n"
2352 "#  endif\n"
2353 "# endif\n"
2354 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2355 "\n"
2356 "#ifdef USESHADOWMAPCUBE\n"
2357 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2358 "{\n"
2359 "    float3 adir = abs(dir);\n"
2360 "    return float4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
2361 "}\n"
2362 "#endif\n"
2363 "\n"
2364 "# ifdef USESHADOWMAPRECT\n"
2365 "#ifdef USESHADOWMAPVSDCT\n"
2366 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2367 "#else\n"
2368 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2369 "#endif\n"
2370 "{\n"
2371 "#ifdef USESHADOWMAPVSDCT\n"
2372 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2373 "#else\n"
2374 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2375 "#endif\n"
2376 "       float f;\n"
2377 "#  ifdef USESHADOWSAMPLER\n"
2378 "\n"
2379 "#    ifdef USESHADOWMAPPCF\n"
2380 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2381 "    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"
2382 "#    else\n"
2383 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2384 "#    endif\n"
2385 "\n"
2386 "#  else\n"
2387 "\n"
2388 "#    ifdef USESHADOWMAPPCF\n"
2389 "#      if USESHADOWMAPPCF > 1\n"
2390 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2391 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2392 "    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"
2393 "    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"
2394 "    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"
2395 "    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"
2396 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2397 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2398 "#      else\n"
2399 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2400 "    float2 offset = frac(shadowmaptc.xy);\n"
2401 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2402 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2403 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2404 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2405 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2406 "#      endif\n"
2407 "#    else\n"
2408 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2409 "#    endif\n"
2410 "\n"
2411 "#  endif\n"
2412 "#  ifdef USESHADOWMAPORTHO\n"
2413 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2414 "#  else\n"
2415 "       return f;\n"
2416 "#  endif\n"
2417 "}\n"
2418 "# endif\n"
2419 "\n"
2420 "# ifdef USESHADOWMAP2D\n"
2421 "#ifdef USESHADOWMAPVSDCT\n"
2422 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2423 "#else\n"
2424 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2425 "#endif\n"
2426 "{\n"
2427 "#ifdef USESHADOWMAPVSDCT\n"
2428 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2429 "#else\n"
2430 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2431 "#endif\n"
2432 "    float f;\n"
2433 "\n"
2434 "#  ifdef USESHADOWSAMPLER\n"
2435 "#    ifdef USESHADOWMAPPCF\n"
2436 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2437 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2438 "    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"
2439 "#    else\n"
2440 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2441 "#    endif\n"
2442 "#  else\n"
2443 "#    ifdef USESHADOWMAPPCF\n"
2444 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2445 "#      ifdef GL_ARB_texture_gather\n"
2446 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2447 "#      else\n"
2448 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2449 "#      endif\n"
2450 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2451 "    center *= ShadowMap_TextureScale;\n"
2452 "    float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2453 "    float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2454 "    float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2455 "    float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2456 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2457 "                lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2458 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2459 "#     else\n"
2460 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)  \n"
2461 "#      if USESHADOWMAPPCF > 1\n"
2462 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2463 "    center *= ShadowMap_TextureScale;\n"
2464 "    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"
2465 "    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"
2466 "    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"
2467 "    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"
2468 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2469 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2470 "#      else\n"
2471 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2472 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2473 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2474 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2475 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2476 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2477 "#      endif\n"
2478 "#     endif\n"
2479 "#    else\n"
2480 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2481 "#    endif\n"
2482 "#  endif\n"
2483 "#  ifdef USESHADOWMAPORTHO\n"
2484 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2485 "#  else\n"
2486 "       return f;\n"
2487 "#  endif\n"
2488 "}\n"
2489 "# endif\n"
2490 "\n"
2491 "# ifdef USESHADOWMAPCUBE\n"
2492 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2493 "{\n"
2494 "    // apply depth texture cubemap as light filter\n"
2495 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2496 "    float f;\n"
2497 "#  ifdef USESHADOWSAMPLER\n"
2498 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2499 "#  else\n"
2500 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2501 "#  endif\n"
2502 "    return f;\n"
2503 "}\n"
2504 "# endif\n"
2505 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2506 "#endif // FRAGMENT_SHADER\n"
2507 "\n"
2508 "\n"
2509 "\n"
2510 "\n"
2511 "#ifdef MODE_DEFERREDGEOMETRY\n"
2512 "#ifdef VERTEX_SHADER\n"
2513 "void main\n"
2514 "(\n"
2515 "float4 gl_Vertex : POSITION,\n"
2516 "uniform float4x4 ModelViewProjectionMatrix,\n"
2517 "#ifdef USEVERTEXTEXTUREBLEND\n"
2518 "float4 gl_Color : COLOR0,\n"
2519 "#endif\n"
2520 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2521 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2522 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2523 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2524 "uniform float4x4 TexMatrix,\n"
2525 "#ifdef USEVERTEXTEXTUREBLEND\n"
2526 "uniform float4x4 BackgroundTexMatrix,\n"
2527 "#endif\n"
2528 "uniform float4x4 ModelViewMatrix,\n"
2529 "#ifdef USEOFFSETMAPPING\n"
2530 "uniform float3 EyePosition,\n"
2531 "#endif\n"
2532 "out float4 gl_Position : POSITION,\n"
2533 "out float4 gl_FrontColor : COLOR,\n"
2534 "out float4 TexCoordBoth : TEXCOORD0,\n"
2535 "#ifdef USEOFFSETMAPPING\n"
2536 "out float3 EyeVector : TEXCOORD2,\n"
2537 "#endif\n"
2538 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2539 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2540 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2541 ")\n"
2542 "{\n"
2543 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2544 "#ifdef USEVERTEXTEXTUREBLEND\n"
2545 "       gl_FrontColor = gl_Color;\n"
2546 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2547 "#endif\n"
2548 "\n"
2549 "       // transform unnormalized eye direction into tangent space\n"
2550 "#ifdef USEOFFSETMAPPING\n"
2551 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2552 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2553 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2554 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2555 "#endif\n"
2556 "\n"
2557 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2558 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2559 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2560 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2561 "}\n"
2562 "#endif // VERTEX_SHADER\n"
2563 "\n"
2564 "#ifdef FRAGMENT_SHADER\n"
2565 "void main\n"
2566 "(\n"
2567 "float4 TexCoordBoth : TEXCOORD0,\n"
2568 "float3 EyeVector : TEXCOORD2,\n"
2569 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2570 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2571 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2572 "uniform sampler2D Texture_Normal,\n"
2573 "#ifdef USEALPHAKILL\n"
2574 "uniform sampler2D Texture_Color,\n"
2575 "#endif\n"
2576 "uniform sampler2D Texture_Gloss,\n"
2577 "#ifdef USEVERTEXTEXTUREBLEND\n"
2578 "uniform sampler2D Texture_SecondaryNormal,\n"
2579 "uniform sampler2D Texture_SecondaryGloss,\n"
2580 "#endif\n"
2581 "#ifdef USEOFFSETMAPPING\n"
2582 "uniform float OffsetMapping_Scale,\n"
2583 "#endif\n"
2584 "uniform half SpecularPower,\n"
2585 "out float4 gl_FragColor : COLOR\n"
2586 ")\n"
2587 "{\n"
2588 "       float2 TexCoord = TexCoordBoth.xy;\n"
2589 "#ifdef USEOFFSETMAPPING\n"
2590 "       // apply offsetmapping\n"
2591 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2592 "#define TexCoord TexCoordOffset\n"
2593 "#endif\n"
2594 "\n"
2595 "#ifdef USEALPHAKILL\n"
2596 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2597 "               discard;\n"
2598 "#endif\n"
2599 "\n"
2600 "#ifdef USEVERTEXTEXTUREBLEND\n"
2601 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2602 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2603 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2604 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2605 "#endif\n"
2606 "\n"
2607 "#ifdef USEVERTEXTEXTUREBLEND\n"
2608 "       float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2609 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2610 "#else\n"
2611 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2612 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2613 "#endif\n"
2614 "\n"
2615 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2616 "}\n"
2617 "#endif // FRAGMENT_SHADER\n"
2618 "#else // !MODE_DEFERREDGEOMETRY\n"
2619 "\n"
2620 "\n"
2621 "\n"
2622 "\n"
2623 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2624 "#ifdef VERTEX_SHADER\n"
2625 "void main\n"
2626 "(\n"
2627 "float4 gl_Vertex : POSITION,\n"
2628 "uniform float4x4 ModelViewProjectionMatrix,\n"
2629 "uniform float4x4 ModelViewMatrix,\n"
2630 "out float4 gl_Position : POSITION,\n"
2631 "out float4 ModelViewPosition : TEXCOORD0\n"
2632 ")\n"
2633 "{\n"
2634 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2635 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2636 "}\n"
2637 "#endif // VERTEX_SHADER\n"
2638 "\n"
2639 "#ifdef FRAGMENT_SHADER\n"
2640 "void main\n"
2641 "(\n"
2642 "float2 Pixel : WPOS,\n"
2643 "float4 ModelViewPosition : TEXCOORD0,\n"
2644 "uniform float4x4 ViewToLight,\n"
2645 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2646 "uniform float3 LightPosition,\n"
2647 "uniform half2 PixelToScreenTexCoord,\n"
2648 "uniform half3 DeferredColor_Ambient,\n"
2649 "uniform half3 DeferredColor_Diffuse,\n"
2650 "#ifdef USESPECULAR\n"
2651 "uniform half3 DeferredColor_Specular,\n"
2652 "uniform half SpecularPower,\n"
2653 "#endif\n"
2654 "uniform sampler2D Texture_Attenuation,\n"
2655 "uniform sampler2D Texture_ScreenDepth,\n"
2656 "uniform sampler2D Texture_ScreenNormalMap,\n"
2657 "\n"
2658 "#ifdef USECUBEFILTER\n"
2659 "uniform samplerCUBE Texture_Cube,\n"
2660 "#endif\n"
2661 "\n"
2662 "#ifdef USESHADOWMAPRECT\n"
2663 "# ifdef USESHADOWSAMPLER\n"
2664 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2665 "# else\n"
2666 "uniform samplerRECT Texture_ShadowMapRect,\n"
2667 "# endif\n"
2668 "#endif\n"
2669 "\n"
2670 "#ifdef USESHADOWMAP2D\n"
2671 "# ifdef USESHADOWSAMPLER\n"
2672 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2673 "# else\n"
2674 "uniform sampler2D Texture_ShadowMap2D,\n"
2675 "# endif\n"
2676 "#endif\n"
2677 "\n"
2678 "#ifdef USESHADOWMAPVSDCT\n"
2679 "uniform samplerCUBE Texture_CubeProjection,\n"
2680 "#endif\n"
2681 "\n"
2682 "#ifdef USESHADOWMAPCUBE\n"
2683 "# ifdef USESHADOWSAMPLER\n"
2684 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2685 "# else\n"
2686 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2687 "# endif\n"
2688 "#endif\n"
2689 "\n"
2690 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2691 "uniform float2 ShadowMap_TextureScale,\n"
2692 "uniform float4 ShadowMap_Parameters,\n"
2693 "#endif\n"
2694 "\n"
2695 "out float4 gl_FragData0 : COLOR0,\n"
2696 "out float4 gl_FragData1 : COLOR1\n"
2697 ")\n"
2698 "{\n"
2699 "       // calculate viewspace pixel position\n"
2700 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2701 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2702 "       float3 position;\n"
2703 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2704 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2705 "       // decode viewspace pixel normal\n"
2706 "       half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2707 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2708 "       // surfacenormal = pixel normal in viewspace\n"
2709 "       // LightVector = pixel to light in viewspace\n"
2710 "       // CubeVector = position in lightspace\n"
2711 "       // eyevector = pixel to view in viewspace\n"
2712 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2713 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2714 "#ifdef USEDIFFUSE\n"
2715 "       // calculate diffuse shading\n"
2716 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2717 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2718 "#endif\n"
2719 "#ifdef USESPECULAR\n"
2720 "       // calculate directional shading\n"
2721 "       float3 eyevector = position * -1.0;\n"
2722 "#  ifdef USEEXACTSPECULARMATH\n"
2723 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2724 "#  else\n"
2725 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2726 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2727 "#  endif\n"
2728 "#endif\n"
2729 "\n"
2730 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2731 "       fade *= ShadowMapCompare(CubeVector,\n"
2732 "# if defined(USESHADOWMAP2D)\n"
2733 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2734 "# endif\n"
2735 "# if defined(USESHADOWMAPRECT)\n"
2736 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2737 "# endif\n"
2738 "# if defined(USESHADOWMAPCUBE)\n"
2739 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2740 "# endif\n"
2741 "\n"
2742 "#ifdef USESHADOWMAPVSDCT\n"
2743 ", Texture_CubeProjection\n"
2744 "#endif\n"
2745 "       );\n"
2746 "#endif\n"
2747 "\n"
2748 "#ifdef USEDIFFUSE\n"
2749 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2750 "#else\n"
2751 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2752 "#endif\n"
2753 "#ifdef USESPECULAR\n"
2754 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2755 "#else\n"
2756 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2757 "#endif\n"
2758 "\n"
2759 "# ifdef USECUBEFILTER\n"
2760 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2761 "       gl_FragData0.rgb *= cubecolor;\n"
2762 "       gl_FragData1.rgb *= cubecolor;\n"
2763 "# endif\n"
2764 "}\n"
2765 "#endif // FRAGMENT_SHADER\n"
2766 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2767 "\n"
2768 "\n"
2769 "\n"
2770 "\n"
2771 "#ifdef VERTEX_SHADER\n"
2772 "void main\n"
2773 "(\n"
2774 "float4 gl_Vertex : POSITION,\n"
2775 "uniform float4x4 ModelViewProjectionMatrix,\n"
2776 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2777 "float4 gl_Color : COLOR0,\n"
2778 "#endif\n"
2779 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2780 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2781 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2782 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2783 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2784 "\n"
2785 "uniform float3 EyePosition,\n"
2786 "uniform float4x4 TexMatrix,\n"
2787 "#ifdef USEVERTEXTEXTUREBLEND\n"
2788 "uniform float4x4 BackgroundTexMatrix,\n"
2789 "#endif\n"
2790 "#ifdef MODE_LIGHTSOURCE\n"
2791 "uniform float4x4 ModelToLight,\n"
2792 "#endif\n"
2793 "#ifdef MODE_LIGHTSOURCE\n"
2794 "uniform float3 LightPosition,\n"
2795 "#endif\n"
2796 "#ifdef MODE_LIGHTDIRECTION\n"
2797 "uniform float3 LightDir,\n"
2798 "#endif\n"
2799 "uniform float4 FogPlane,\n"
2800 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2801 "uniform float3 LightPosition,\n"
2802 "#endif\n"
2803 "#ifdef USESHADOWMAPORTHO\n"
2804 "uniform float4x4 ShadowMapMatrix,\n"
2805 "#endif\n"
2806 "\n"
2807 "out float4 gl_FrontColor : COLOR,\n"
2808 "out float4 TexCoordBoth : TEXCOORD0,\n"
2809 "#ifdef USELIGHTMAP\n"
2810 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2811 "#endif\n"
2812 "#ifdef USEEYEVECTOR\n"
2813 "out float3 EyeVector : TEXCOORD2,\n"
2814 "#endif\n"
2815 "#ifdef USEREFLECTION\n"
2816 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2817 "#endif\n"
2818 "#ifdef USEFOG\n"
2819 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2820 "#endif\n"
2821 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2822 "out float3 LightVector : TEXCOORD1,\n"
2823 "#endif\n"
2824 "#ifdef MODE_LIGHTSOURCE\n"
2825 "out float3 CubeVector : TEXCOORD3,\n"
2826 "#endif\n"
2827 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2828 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2829 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2830 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2831 "#endif\n"
2832 "#ifdef USESHADOWMAPORTHO\n"
2833 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2834 "#endif\n"
2835 "out float4 gl_Position : POSITION\n"
2836 ")\n"
2837 "{\n"
2838 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2839 "       gl_FrontColor = gl_Color;\n"
2840 "#endif\n"
2841 "       // copy the surface texcoord\n"
2842 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2843 "#ifdef USEVERTEXTEXTUREBLEND\n"
2844 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2845 "#endif\n"
2846 "#ifdef USELIGHTMAP\n"
2847 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2848 "#endif\n"
2849 "\n"
2850 "#ifdef MODE_LIGHTSOURCE\n"
2851 "       // transform vertex position into light attenuation/cubemap space\n"
2852 "       // (-1 to +1 across the light box)\n"
2853 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2854 "\n"
2855 "# ifdef USEDIFFUSE\n"
2856 "       // transform unnormalized light direction into tangent space\n"
2857 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2858 "       //  normalize it per pixel)\n"
2859 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2860 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2861 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2862 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2863 "# endif\n"
2864 "#endif\n"
2865 "\n"
2866 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2867 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2868 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2869 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2870 "#endif\n"
2871 "\n"
2872 "       // transform unnormalized eye direction into tangent space\n"
2873 "#ifdef USEEYEVECTOR\n"
2874 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2875 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2876 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2877 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2878 "#endif\n"
2879 "\n"
2880 "#ifdef USEFOG\n"
2881 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2882 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2883 "#endif\n"
2884 "\n"
2885 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2886 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2887 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2888 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2889 "#endif\n"
2890 "\n"
2891 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2892 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2893 "\n"
2894 "#ifdef USESHADOWMAPORTHO\n"
2895 "       ShadowMapTC = float3(mul(ShadowMapMatrix, gl_Position));\n"
2896 "#endif\n"
2897 "\n"
2898 "#ifdef USEREFLECTION\n"
2899 "       ModelViewProjectionPosition = gl_Position;\n"
2900 "#endif\n"
2901 "}\n"
2902 "#endif // VERTEX_SHADER\n"
2903 "\n"
2904 "\n"
2905 "\n"
2906 "\n"
2907 "#ifdef FRAGMENT_SHADER\n"
2908 "void main\n"
2909 "(\n"
2910 "#ifdef USEDEFERREDLIGHTMAP\n"
2911 "float2 Pixel : WPOS,\n"
2912 "#endif\n"
2913 "float4 gl_FrontColor : COLOR,\n"
2914 "float4 TexCoordBoth : TEXCOORD0,\n"
2915 "#ifdef USELIGHTMAP\n"
2916 "float2 TexCoordLightmap : TEXCOORD1,\n"
2917 "#endif\n"
2918 "#ifdef USEEYEVECTOR\n"
2919 "float3 EyeVector : TEXCOORD2,\n"
2920 "#endif\n"
2921 "#ifdef USEREFLECTION\n"
2922 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2923 "#endif\n"
2924 "#ifdef USEFOG\n"
2925 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2926 "#endif\n"
2927 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2928 "float3 LightVector : TEXCOORD1,\n"
2929 "#endif\n"
2930 "#ifdef MODE_LIGHTSOURCE\n"
2931 "float3 CubeVector : TEXCOORD3,\n"
2932 "#endif\n"
2933 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2934 "float4 ModelViewPosition : TEXCOORD0,\n"
2935 "#endif\n"
2936 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2937 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2938 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2939 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2940 "#endif\n"
2941 "#ifdef USESHADOWMAPORTHO\n"
2942 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2943 "#endif\n"
2944 "\n"
2945 "uniform sampler2D Texture_Normal,\n"
2946 "uniform sampler2D Texture_Color,\n"
2947 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2948 "uniform sampler2D Texture_Gloss,\n"
2949 "#endif\n"
2950 "#ifdef USEGLOW\n"
2951 "uniform sampler2D Texture_Glow,\n"
2952 "#endif\n"
2953 "#ifdef USEVERTEXTEXTUREBLEND\n"
2954 "uniform sampler2D Texture_SecondaryNormal,\n"
2955 "uniform sampler2D Texture_SecondaryColor,\n"
2956 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2957 "uniform sampler2D Texture_SecondaryGloss,\n"
2958 "#endif\n"
2959 "#ifdef USEGLOW\n"
2960 "uniform sampler2D Texture_SecondaryGlow,\n"
2961 "#endif\n"
2962 "#endif\n"
2963 "#ifdef USECOLORMAPPING\n"
2964 "uniform sampler2D Texture_Pants,\n"
2965 "uniform sampler2D Texture_Shirt,\n"
2966 "#endif\n"
2967 "#ifdef USEFOG\n"
2968 "uniform sampler2D Texture_FogHeightTexture,\n"
2969 "uniform sampler2D Texture_FogMask,\n"
2970 "#endif\n"
2971 "#ifdef USELIGHTMAP\n"
2972 "uniform sampler2D Texture_Lightmap,\n"
2973 "#endif\n"
2974 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2975 "uniform sampler2D Texture_Deluxemap,\n"
2976 "#endif\n"
2977 "#ifdef USEREFLECTION\n"
2978 "uniform sampler2D Texture_Reflection,\n"
2979 "#endif\n"
2980 "\n"
2981 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2982 "uniform sampler2D Texture_ScreenDepth,\n"
2983 "uniform sampler2D Texture_ScreenNormalMap,\n"
2984 "#endif\n"
2985 "#ifdef USEDEFERREDLIGHTMAP\n"
2986 "uniform sampler2D Texture_ScreenDiffuse,\n"
2987 "uniform sampler2D Texture_ScreenSpecular,\n"
2988 "#endif\n"
2989 "\n"
2990 "#ifdef USECOLORMAPPING\n"
2991 "uniform half3 Color_Pants,\n"
2992 "uniform half3 Color_Shirt,\n"
2993 "#endif\n"
2994 "#ifdef USEFOG\n"
2995 "uniform float3 FogColor,\n"
2996 "uniform float FogRangeRecip,\n"
2997 "uniform float FogPlaneViewDist,\n"
2998 "uniform float FogHeightFade,\n"
2999 "#endif\n"
3000 "\n"
3001 "#ifdef USEOFFSETMAPPING\n"
3002 "uniform float OffsetMapping_Scale,\n"
3003 "#endif\n"
3004 "\n"
3005 "#ifdef USEDEFERREDLIGHTMAP\n"
3006 "uniform half2 PixelToScreenTexCoord,\n"
3007 "uniform half3 DeferredMod_Diffuse,\n"
3008 "uniform half3 DeferredMod_Specular,\n"
3009 "#endif\n"
3010 "uniform half3 Color_Ambient,\n"
3011 "uniform half3 Color_Diffuse,\n"
3012 "uniform half3 Color_Specular,\n"
3013 "uniform half SpecularPower,\n"
3014 "#ifdef USEGLOW\n"
3015 "uniform half3 Color_Glow,\n"
3016 "#endif\n"
3017 "uniform half Alpha,\n"
3018 "#ifdef USEREFLECTION\n"
3019 "uniform float4 DistortScaleRefractReflect,\n"
3020 "uniform float4 ScreenScaleRefractReflect,\n"
3021 "uniform float4 ScreenCenterRefractReflect,\n"
3022 "uniform half4 ReflectColor,\n"
3023 "#endif\n"
3024 "#ifdef USEREFLECTCUBE\n"
3025 "uniform float4x4 ModelToReflectCube,\n"
3026 "uniform sampler2D Texture_ReflectMask,\n"
3027 "uniform samplerCUBE Texture_ReflectCube,\n"
3028 "#endif\n"
3029 "#ifdef MODE_LIGHTDIRECTION\n"
3030 "uniform half3 LightColor,\n"
3031 "#endif\n"
3032 "#ifdef MODE_LIGHTSOURCE\n"
3033 "uniform half3 LightColor,\n"
3034 "#endif\n"
3035 "\n"
3036 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3037 "uniform sampler2D Texture_Attenuation,\n"
3038 "uniform samplerCUBE Texture_Cube,\n"
3039 "#endif\n"
3040 "\n"
3041 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3042 "\n"
3043 "#ifdef USESHADOWMAPRECT\n"
3044 "# ifdef USESHADOWSAMPLER\n"
3045 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
3046 "# else\n"
3047 "uniform samplerRECT Texture_ShadowMapRect,\n"
3048 "# endif\n"
3049 "#endif\n"
3050 "\n"
3051 "#ifdef USESHADOWMAP2D\n"
3052 "# ifdef USESHADOWSAMPLER\n"
3053 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
3054 "# else\n"
3055 "uniform sampler2D Texture_ShadowMap2D,\n"
3056 "# endif\n"
3057 "#endif\n"
3058 "\n"
3059 "#ifdef USESHADOWMAPVSDCT\n"
3060 "uniform samplerCUBE Texture_CubeProjection,\n"
3061 "#endif\n"
3062 "\n"
3063 "#ifdef USESHADOWMAPCUBE\n"
3064 "# ifdef USESHADOWSAMPLER\n"
3065 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
3066 "# else\n"
3067 "uniform samplerCUBE Texture_ShadowMapCube,\n"
3068 "# endif\n"
3069 "#endif\n"
3070 "\n"
3071 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
3072 "uniform float2 ShadowMap_TextureScale,\n"
3073 "uniform float4 ShadowMap_Parameters,\n"
3074 "#endif\n"
3075 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3076 "\n"
3077 "out float4 gl_FragColor : COLOR\n"
3078 ")\n"
3079 "{\n"
3080 "       float2 TexCoord = TexCoordBoth.xy;\n"
3081 "#ifdef USEVERTEXTEXTUREBLEND\n"
3082 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3083 "#endif\n"
3084 "#ifdef USEOFFSETMAPPING\n"
3085 "       // apply offsetmapping\n"
3086 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3087 "#define TexCoord TexCoordOffset\n"
3088 "#endif\n"
3089 "\n"
3090 "       // combine the diffuse textures (base, pants, shirt)\n"
3091 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3092 "#ifdef USEALPHAKILL\n"
3093 "       if (color.a < 0.5)\n"
3094 "               discard;\n"
3095 "#endif\n"
3096 "       color.a *= Alpha;\n"
3097 "#ifdef USECOLORMAPPING\n"
3098 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
3099 "#endif\n"
3100 "#ifdef USEVERTEXTEXTUREBLEND\n"
3101 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3102 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3103 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3104 "       color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
3105 "       color.a = 1.0;\n"
3106 "       //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
3107 "#endif\n"
3108 "\n"
3109 "       // get the surface normal\n"
3110 "#ifdef USEVERTEXTEXTUREBLEND\n"
3111 "       half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3112 "#else\n"
3113 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
3114 "#endif\n"
3115 "\n"
3116 "       // get the material colors\n"
3117 "       half3 diffusetex = color.rgb;\n"
3118 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3119 "# ifdef USEVERTEXTEXTUREBLEND\n"
3120 "       half4 glosstex = half4(lerp(float4(tex2D(Texture_SecondaryGloss, TexCoord2)), float4(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
3121 "# else\n"
3122 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3123 "# endif\n"
3124 "#endif\n"
3125 "\n"
3126 "#ifdef USEREFLECTCUBE\n"
3127 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3128 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3129 "       float3 ReflectCubeTexCoord = float3(mul(ModelToReflectCube, float4(ModelReflectVector, 0)));\n"
3130 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord)) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord));\n"
3131 "#endif\n"
3132 "\n"
3133 "\n"
3134 "\n"
3135 "\n"
3136 "#ifdef MODE_LIGHTSOURCE\n"
3137 "       // light source\n"
3138 "#ifdef USEDIFFUSE\n"
3139 "       half3 lightnormal = half3(normalize(LightVector));\n"
3140 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3141 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3142 "#ifdef USESPECULAR\n"
3143 "#ifdef USEEXACTSPECULARMATH\n"
3144 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3145 "#else\n"
3146 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3147 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3148 "#endif\n"
3149 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3150 "#endif\n"
3151 "#else\n"
3152 "       color.rgb = diffusetex * Color_Ambient;\n"
3153 "#endif\n"
3154 "       color.rgb *= LightColor;\n"
3155 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
3156 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3157 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
3158 "# if defined(USESHADOWMAP2D)\n"
3159 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3160 "# endif\n"
3161 "# if defined(USESHADOWMAPRECT)\n"
3162 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3163 "# endif\n"
3164 "# if defined(USESHADOWMAPCUBE)\n"
3165 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3166 "# endif\n"
3167 "\n"
3168 "#ifdef USESHADOWMAPVSDCT\n"
3169 ", Texture_CubeProjection\n"
3170 "#endif\n"
3171 "       );\n"
3172 "\n"
3173 "#endif\n"
3174 "# ifdef USECUBEFILTER\n"
3175 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
3176 "# endif\n"
3177 "#endif // MODE_LIGHTSOURCE\n"
3178 "\n"
3179 "\n"
3180 "\n"
3181 "\n"
3182 "#ifdef MODE_LIGHTDIRECTION\n"
3183 "#define SHADING\n"
3184 "#ifdef USEDIFFUSE\n"
3185 "       half3 lightnormal = half3(normalize(LightVector));\n"
3186 "#endif\n"
3187 "#define lightcolor LightColor\n"
3188 "#endif // MODE_LIGHTDIRECTION\n"
3189 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3190 "#define SHADING\n"
3191 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3192 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3193 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3194 "       // convert modelspace light vector to tangentspace\n"
3195 "       half3 lightnormal;\n"
3196 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3197 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3198 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3199 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3200 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3201 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3202 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3203 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3204 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3205 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3206 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3207 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3208 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3209 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3210 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3211 "#define SHADING\n"
3212 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3213 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3214 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3215 "#endif\n"
3216 "\n"
3217 "\n"
3218 "\n"
3219 "\n"
3220 "#ifdef MODE_LIGHTMAP\n"
3221 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3222 "#endif // MODE_LIGHTMAP\n"
3223 "#ifdef MODE_VERTEXCOLOR\n"
3224 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3225 "#endif // MODE_VERTEXCOLOR\n"
3226 "#ifdef MODE_FLATCOLOR\n"
3227 "       color.rgb = diffusetex * Color_Ambient;\n"
3228 "#endif // MODE_FLATCOLOR\n"
3229 "\n"
3230 "\n"
3231 "\n"
3232 "\n"
3233 "#ifdef SHADING\n"
3234 "# ifdef USEDIFFUSE\n"
3235 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3236 "#  ifdef USESPECULAR\n"
3237 "#   ifdef USEEXACTSPECULARMATH\n"
3238 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3239 "#   else\n"
3240 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3241 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3242 "#   endif\n"
3243 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3244 "#  else\n"
3245 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3246 "#  endif\n"
3247 "# else\n"
3248 "       color.rgb = diffusetex * Color_Ambient;\n"
3249 "# endif\n"
3250 "#endif\n"
3251 "\n"
3252 "#ifdef USESHADOWMAPORTHO\n"
3253 "       color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3254 "# if defined(USESHADOWMAP2D)\n"
3255 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3256 "# endif\n"
3257 "# if defined(USESHADOWMAPRECT)\n"
3258 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3259 "# endif\n"
3260 "       );\n"
3261 "#endif\n"
3262 "\n"
3263 "#ifdef USEDEFERREDLIGHTMAP\n"
3264 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3265 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3266 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3267 "#endif\n"
3268 "\n"
3269 "#ifdef USEGLOW\n"
3270 "#ifdef USEVERTEXTEXTUREBLEND\n"
3271 "       color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3272 "#else\n"
3273 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3274 "#endif\n"
3275 "#endif\n"
3276 "\n"
3277 "#ifdef USEFOG\n"
3278 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3279 "#endif\n"
3280 "\n"
3281 "       // 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"
3282 "#ifdef USEREFLECTION\n"
3283 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3284 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3285 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3286 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3287 "       // FIXME temporary hack to detect the case that the reflection\n"
3288 "       // gets blackened at edges due to leaving the area that contains actual\n"
3289 "       // content.\n"
3290 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3291 "       // 'appening.\n"
3292 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3293 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3294 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3295 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3296 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3297 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3298 "#endif\n"
3299 "\n"
3300 "       gl_FragColor = float4(color);\n"
3301 "}\n"
3302 "#endif // FRAGMENT_SHADER\n"
3303 "\n"
3304 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3305 "#endif // !MODE_DEFERREDGEOMETRY\n"
3306 "#endif // !MODE_WATER\n"
3307 "#endif // !MODE_REFRACTION\n"
3308 "#endif // !MODE_BLOOMBLUR\n"
3309 "#endif // !MODE_GENERIC\n"
3310 "#endif // !MODE_POSTPROCESS\n"
3311 "#endif // !MODE_SHOWDEPTH\n"
3312 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3313 ;
3314
3315 char *glslshaderstring = NULL;
3316 char *cgshaderstring = NULL;
3317
3318 //=======================================================================================================================================================
3319
3320 typedef struct shaderpermutationinfo_s
3321 {
3322         const char *pretext;
3323         const char *name;
3324 }
3325 shaderpermutationinfo_t;
3326
3327 typedef struct shadermodeinfo_s
3328 {
3329         const char *vertexfilename;
3330         const char *geometryfilename;
3331         const char *fragmentfilename;
3332         const char *pretext;
3333         const char *name;
3334 }
3335 shadermodeinfo_t;
3336
3337 typedef enum shaderpermutation_e
3338 {
3339         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3340         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3341         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3342         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3343         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3344         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3345         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3346         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3347         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3348         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3349         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3350         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3351         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3352         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3353         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3354         SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3355         SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3356         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3357         SHADERPERMUTATION_SHADOWMAPRECT = 1<<18, ///< (lightsource) use shadowmap rectangle texture as light filter
3358         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<19, ///< (lightsource) use shadowmap cubemap texture as light filter
3359         SHADERPERMUTATION_SHADOWMAP2D = 1<<20, ///< (lightsource) use shadowmap rectangle texture as light filter
3360         SHADERPERMUTATION_SHADOWMAPPCF = 1<<21, ///< (lightsource) use percentage closer filtering on shadowmap test results
3361         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<22, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3362         SHADERPERMUTATION_SHADOWSAMPLER = 1<<23, ///< (lightsource) use hardware shadowmap test
3363         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<24, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3364         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<25, //< (lightsource) use orthographic shadowmap projection
3365         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<26, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3366         SHADERPERMUTATION_ALPHAKILL = 1<<27, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3367         SHADERPERMUTATION_REFLECTCUBE = 1<<28, ///< fake reflections using global cubemap (not HDRI light probe)
3368         SHADERPERMUTATION_LIMIT = 1<<29, ///< size of permutations array
3369         SHADERPERMUTATION_COUNT = 29 ///< size of shaderpermutationinfo array
3370 }
3371 shaderpermutation_t;
3372
3373 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3374 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3375 {
3376         {"#define USEDIFFUSE\n", " diffuse"},
3377         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3378         {"#define USEVIEWTINT\n", " viewtint"},
3379         {"#define USECOLORMAPPING\n", " colormapping"},
3380         {"#define USESATURATION\n", " saturation"},
3381         {"#define USEFOGINSIDE\n", " foginside"},
3382         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3383         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3384         {"#define USEGAMMARAMPS\n", " gammaramps"},
3385         {"#define USECUBEFILTER\n", " cubefilter"},
3386         {"#define USEGLOW\n", " glow"},
3387         {"#define USEBLOOM\n", " bloom"},
3388         {"#define USESPECULAR\n", " specular"},
3389         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3390         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3391         {"#define USEREFLECTION\n", " reflection"},
3392         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3393         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3394         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3395         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3396         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3397         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3398         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3399         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3400         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3401         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3402         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3403         {"#define USEALPHAKILL\n", " alphakill"},
3404         {"#define USEREFLECTCUBE\n", " reflectcube"},
3405 };
3406
3407 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3408 typedef enum shadermode_e
3409 {
3410         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3411         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3412         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3413         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3414         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3415         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3416         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3417         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3418         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3419         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3420         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3421         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3422         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3423         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3424         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3425         SHADERMODE_COUNT
3426 }
3427 shadermode_t;
3428
3429 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3430 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3431 {
3432         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3433         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3434         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3435         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3436         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3437         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3438         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3439         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3440         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3441         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3442         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3443         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3444         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3445         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3446         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3447 };
3448
3449 #ifdef SUPPORTCG
3450 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3451 {
3452         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3453         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3454         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3455         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3456         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3457         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3458         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3459         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3460         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3461         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3462         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3463         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3464         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3465         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3466         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3467 };
3468 #endif
3469
3470 struct r_glsl_permutation_s;
3471 typedef struct r_glsl_permutation_s
3472 {
3473         /// hash lookup data
3474         struct r_glsl_permutation_s *hashnext;
3475         unsigned int mode;
3476         unsigned int permutation;
3477
3478         /// indicates if we have tried compiling this permutation already
3479         qboolean compiled;
3480         /// 0 if compilation failed
3481         int program;
3482         /// locations of detected uniforms in program object, or -1 if not found
3483         int loc_Texture_First;
3484         int loc_Texture_Second;
3485         int loc_Texture_GammaRamps;
3486         int loc_Texture_Normal;
3487         int loc_Texture_Color;
3488         int loc_Texture_Gloss;
3489         int loc_Texture_Glow;
3490         int loc_Texture_SecondaryNormal;
3491         int loc_Texture_SecondaryColor;
3492         int loc_Texture_SecondaryGloss;
3493         int loc_Texture_SecondaryGlow;
3494         int loc_Texture_Pants;
3495         int loc_Texture_Shirt;
3496         int loc_Texture_FogHeightTexture;
3497         int loc_Texture_FogMask;
3498         int loc_Texture_Lightmap;
3499         int loc_Texture_Deluxemap;
3500         int loc_Texture_Attenuation;
3501         int loc_Texture_Cube;
3502         int loc_Texture_Refraction;
3503         int loc_Texture_Reflection;
3504         int loc_Texture_ShadowMapRect;
3505         int loc_Texture_ShadowMapCube;
3506         int loc_Texture_ShadowMap2D;
3507         int loc_Texture_CubeProjection;
3508         int loc_Texture_ScreenDepth;
3509         int loc_Texture_ScreenNormalMap;
3510         int loc_Texture_ScreenDiffuse;
3511         int loc_Texture_ScreenSpecular;
3512         int loc_Texture_ReflectMask;
3513         int loc_Texture_ReflectCube;
3514         int loc_Alpha;
3515         int loc_BloomBlur_Parameters;
3516         int loc_ClientTime;
3517         int loc_Color_Ambient;
3518         int loc_Color_Diffuse;
3519         int loc_Color_Specular;
3520         int loc_Color_Glow;
3521         int loc_Color_Pants;
3522         int loc_Color_Shirt;
3523         int loc_DeferredColor_Ambient;
3524         int loc_DeferredColor_Diffuse;
3525         int loc_DeferredColor_Specular;
3526         int loc_DeferredMod_Diffuse;
3527         int loc_DeferredMod_Specular;
3528         int loc_DistortScaleRefractReflect;
3529         int loc_EyePosition;
3530         int loc_FogColor;
3531         int loc_FogHeightFade;
3532         int loc_FogPlane;
3533         int loc_FogPlaneViewDist;
3534         int loc_FogRangeRecip;
3535         int loc_LightColor;
3536         int loc_LightDir;
3537         int loc_LightPosition;
3538         int loc_OffsetMapping_Scale;
3539         int loc_PixelSize;
3540         int loc_ReflectColor;
3541         int loc_ReflectFactor;
3542         int loc_ReflectOffset;
3543         int loc_RefractColor;
3544         int loc_Saturation;
3545         int loc_ScreenCenterRefractReflect;
3546         int loc_ScreenScaleRefractReflect;
3547         int loc_ScreenToDepth;
3548         int loc_ShadowMap_Parameters;
3549         int loc_ShadowMap_TextureScale;
3550         int loc_SpecularPower;
3551         int loc_UserVec1;
3552         int loc_UserVec2;
3553         int loc_UserVec3;
3554         int loc_UserVec4;
3555         int loc_ViewTintColor;
3556         int loc_ViewToLight;
3557         int loc_ModelToLight;
3558         int loc_TexMatrix;
3559         int loc_BackgroundTexMatrix;
3560         int loc_ModelViewProjectionMatrix;
3561         int loc_ModelViewMatrix;
3562         int loc_PixelToScreenTexCoord;
3563         int loc_ModelToReflectCube;
3564         int loc_ShadowMapMatrix;        
3565 }
3566 r_glsl_permutation_t;
3567
3568 #define SHADERPERMUTATION_HASHSIZE 256
3569
3570 /// information about each possible shader permutation
3571 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3572 /// currently selected permutation
3573 r_glsl_permutation_t *r_glsl_permutation;
3574 /// storage for permutations linked in the hash table
3575 memexpandablearray_t r_glsl_permutationarray;
3576
3577 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3578 {
3579         //unsigned int hashdepth = 0;
3580         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3581         r_glsl_permutation_t *p;
3582         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3583         {
3584                 if (p->mode == mode && p->permutation == permutation)
3585                 {
3586                         //if (hashdepth > 10)
3587                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3588                         return p;
3589                 }
3590                 //hashdepth++;
3591         }
3592         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3593         p->mode = mode;
3594         p->permutation = permutation;
3595         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3596         r_glsl_permutationhash[mode][hashindex] = p;
3597         //if (hashdepth > 10)
3598         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3599         return p;
3600 }
3601
3602 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3603 {
3604         char *shaderstring;
3605         if (!filename || !filename[0])
3606                 return NULL;
3607         if (!strcmp(filename, "glsl/default.glsl"))
3608         {
3609                 if (!glslshaderstring)
3610                 {
3611                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3612                         if (glslshaderstring)
3613                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3614                         else
3615                                 glslshaderstring = (char *)builtinshaderstring;
3616                 }
3617                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3618                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3619                 return shaderstring;
3620         }
3621         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3622         if (shaderstring)
3623         {
3624                 if (printfromdisknotice)
3625                         Con_DPrintf("from disk %s... ", filename);
3626                 return shaderstring;
3627         }
3628         return shaderstring;
3629 }
3630
3631 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3632 {
3633         int i;
3634         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3635         int vertstrings_count = 0;
3636         int geomstrings_count = 0;
3637         int fragstrings_count = 0;
3638         char *vertexstring, *geometrystring, *fragmentstring;
3639         const char *vertstrings_list[32+3];
3640         const char *geomstrings_list[32+3];
3641         const char *fragstrings_list[32+3];
3642         char permutationname[256];
3643
3644         if (p->compiled)
3645                 return;
3646         p->compiled = true;
3647         p->program = 0;
3648
3649         permutationname[0] = 0;
3650         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3651         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3652         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3653
3654         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3655
3656         // the first pretext is which type of shader to compile as
3657         // (later these will all be bound together as a program object)
3658         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3659         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3660         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3661
3662         // the second pretext is the mode (for example a light source)
3663         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3664         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3665         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3666         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3667
3668         // now add all the permutation pretexts
3669         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3670         {
3671                 if (permutation & (1<<i))
3672                 {
3673                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3674                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3675                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3676                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3677                 }
3678                 else
3679                 {
3680                         // keep line numbers correct
3681                         vertstrings_list[vertstrings_count++] = "\n";
3682                         geomstrings_list[geomstrings_count++] = "\n";
3683                         fragstrings_list[fragstrings_count++] = "\n";
3684                 }
3685         }
3686
3687         // now append the shader text itself
3688         vertstrings_list[vertstrings_count++] = vertexstring;
3689         geomstrings_list[geomstrings_count++] = geometrystring;
3690         fragstrings_list[fragstrings_count++] = fragmentstring;
3691
3692         // if any sources were NULL, clear the respective list
3693         if (!vertexstring)
3694                 vertstrings_count = 0;
3695         if (!geometrystring)
3696                 geomstrings_count = 0;
3697         if (!fragmentstring)
3698                 fragstrings_count = 0;
3699
3700         // compile the shader program
3701         if (vertstrings_count + geomstrings_count + fragstrings_count)
3702                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3703         if (p->program)
3704         {
3705                 CHECKGLERROR
3706                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3707                 // look up all the uniform variable names we care about, so we don't
3708                 // have to look them up every time we set them
3709
3710                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3711                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3712                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3713                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3714                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3715                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3716                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3717                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3718                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3719                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3720                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3721                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3722                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3723                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3724                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3725                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3726                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3727                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3728                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3729                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3730                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3731                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3732                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3733                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3734                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3735                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3736                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3737                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3738                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3739                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3740                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3741                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3742                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3743                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3744                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3745                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3746                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3747                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3748                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3749                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3750                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3751                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3752                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3753                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3754                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3755                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3756                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3757                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3758                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3759                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3760                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3761                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3762                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3763                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3764                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3765                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3766                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3767                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3768                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3769                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3770                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3771                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3772                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3773                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3774                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3775                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3776                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3777                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3778                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3779                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3780                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3781                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3782                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3783                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3784                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3785                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3786                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3787                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3788                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3789                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3790                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3791                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");            
3792                 // initialize the samplers to refer to the texture units we use
3793                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3794                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3795                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3796                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3797                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3798                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3799                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3800                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3801                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3802                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3803                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3804                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3805                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3806                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3807                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3808                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3809                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3810                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3811                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3812                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3813                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3814                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
3815                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3816                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3817                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3818                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3819                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3820                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3821                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3822                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3823                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3824                 CHECKGLERROR
3825                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3826         }
3827         else
3828                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3829
3830         // free the strings
3831         if (vertexstring)
3832                 Mem_Free(vertexstring);
3833         if (geometrystring)
3834                 Mem_Free(geometrystring);
3835         if (fragmentstring)
3836                 Mem_Free(fragmentstring);
3837 }
3838
3839 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3840 {
3841         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3842         if (r_glsl_permutation != perm)
3843         {
3844                 r_glsl_permutation = perm;
3845                 if (!r_glsl_permutation->program)
3846                 {
3847                         if (!r_glsl_permutation->compiled)
3848                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3849                         if (!r_glsl_permutation->program)
3850                         {
3851                                 // remove features until we find a valid permutation
3852                                 int i;
3853                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3854                                 {
3855                                         // reduce i more quickly whenever it would not remove any bits
3856                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3857                                         if (!(permutation & j))
3858                                                 continue;
3859                                         permutation -= j;
3860                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3861                                         if (!r_glsl_permutation->compiled)
3862                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3863                                         if (r_glsl_permutation->program)
3864                                                 break;
3865                                 }
3866                                 if (i >= SHADERPERMUTATION_COUNT)
3867                                 {
3868                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3869                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3870                                         qglUseProgramObjectARB(0);CHECKGLERROR
3871                                         return; // no bit left to clear, entire mode is broken
3872                                 }
3873                         }
3874                 }
3875                 CHECKGLERROR
3876                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3877         }
3878         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3879         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3880         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3881 }
3882
3883 #ifdef SUPPORTCG
3884 #include <Cg/cgGL.h>
3885 struct r_cg_permutation_s;
3886 typedef struct r_cg_permutation_s
3887 {
3888         /// hash lookup data
3889         struct r_cg_permutation_s *hashnext;
3890         unsigned int mode;
3891         unsigned int permutation;
3892
3893         /// indicates if we have tried compiling this permutation already
3894         qboolean compiled;
3895         /// 0 if compilation failed
3896         CGprogram vprogram;
3897         CGprogram fprogram;
3898         /// locations of detected parameters in programs, or NULL if not found
3899         CGparameter vp_EyePosition;
3900         CGparameter vp_FogPlane;
3901         CGparameter vp_LightDir;
3902         CGparameter vp_LightPosition;
3903         CGparameter vp_ModelToLight;
3904         CGparameter vp_TexMatrix;
3905         CGparameter vp_BackgroundTexMatrix;
3906         CGparameter vp_ModelViewProjectionMatrix;
3907         CGparameter vp_ModelViewMatrix;
3908         CGparameter vp_ShadowMapMatrix;
3909
3910         CGparameter fp_Texture_First;
3911         CGparameter fp_Texture_Second;
3912         CGparameter fp_Texture_GammaRamps;
3913         CGparameter fp_Texture_Normal;
3914         CGparameter fp_Texture_Color;
3915         CGparameter fp_Texture_Gloss;
3916         CGparameter fp_Texture_Glow;
3917         CGparameter fp_Texture_SecondaryNormal;
3918         CGparameter fp_Texture_SecondaryColor;
3919         CGparameter fp_Texture_SecondaryGloss;
3920         CGparameter fp_Texture_SecondaryGlow;
3921         CGparameter fp_Texture_Pants;
3922         CGparameter fp_Texture_Shirt;
3923         CGparameter fp_Texture_FogHeightTexture;
3924         CGparameter fp_Texture_FogMask;
3925         CGparameter fp_Texture_Lightmap;
3926         CGparameter fp_Texture_Deluxemap;
3927         CGparameter fp_Texture_Attenuation;
3928         CGparameter fp_Texture_Cube;
3929         CGparameter fp_Texture_Refraction;
3930         CGparameter fp_Texture_Reflection;
3931         CGparameter fp_Texture_ShadowMapRect;
3932         CGparameter fp_Texture_ShadowMapCube;
3933         CGparameter fp_Texture_ShadowMap2D;
3934         CGparameter fp_Texture_CubeProjection;
3935         CGparameter fp_Texture_ScreenDepth;
3936         CGparameter fp_Texture_ScreenNormalMap;
3937         CGparameter fp_Texture_ScreenDiffuse;
3938         CGparameter fp_Texture_ScreenSpecular;
3939         CGparameter fp_Texture_ReflectMask;
3940         CGparameter fp_Texture_ReflectCube;
3941         CGparameter fp_Alpha;
3942         CGparameter fp_BloomBlur_Parameters;
3943         CGparameter fp_ClientTime;
3944         CGparameter fp_Color_Ambient;
3945         CGparameter fp_Color_Diffuse;
3946         CGparameter fp_Color_Specular;
3947         CGparameter fp_Color_Glow;
3948         CGparameter fp_Color_Pants;
3949         CGparameter fp_Color_Shirt;
3950         CGparameter fp_DeferredColor_Ambient;
3951         CGparameter fp_DeferredColor_Diffuse;
3952         CGparameter fp_DeferredColor_Specular;
3953         CGparameter fp_DeferredMod_Diffuse;
3954         CGparameter fp_DeferredMod_Specular;
3955         CGparameter fp_DistortScaleRefractReflect;
3956         CGparameter fp_EyePosition;
3957         CGparameter fp_FogColor;
3958         CGparameter fp_FogHeightFade;
3959         CGparameter fp_FogPlane;
3960         CGparameter fp_FogPlaneViewDist;
3961         CGparameter fp_FogRangeRecip;
3962         CGparameter fp_LightColor;
3963         CGparameter fp_LightDir;
3964         CGparameter fp_LightPosition;
3965         CGparameter fp_OffsetMapping_Scale;
3966         CGparameter fp_PixelSize;
3967         CGparameter fp_ReflectColor;
3968         CGparameter fp_ReflectFactor;
3969         CGparameter fp_ReflectOffset;
3970         CGparameter fp_RefractColor;
3971         CGparameter fp_Saturation;
3972         CGparameter fp_ScreenCenterRefractReflect;
3973         CGparameter fp_ScreenScaleRefractReflect;
3974         CGparameter fp_ScreenToDepth;
3975         CGparameter fp_ShadowMap_Parameters;
3976         CGparameter fp_ShadowMap_TextureScale;
3977         CGparameter fp_SpecularPower;
3978         CGparameter fp_UserVec1;
3979         CGparameter fp_UserVec2;
3980         CGparameter fp_UserVec3;
3981         CGparameter fp_UserVec4;
3982         CGparameter fp_ViewTintColor;
3983         CGparameter fp_ViewToLight;
3984         CGparameter fp_PixelToScreenTexCoord;
3985         CGparameter fp_ModelToReflectCube;
3986 }
3987 r_cg_permutation_t;
3988
3989 /// information about each possible shader permutation
3990 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3991 /// currently selected permutation
3992 r_cg_permutation_t *r_cg_permutation;
3993 /// storage for permutations linked in the hash table
3994 memexpandablearray_t r_cg_permutationarray;
3995
3996 #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));}}
3997
3998 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3999 {
4000         //unsigned int hashdepth = 0;
4001         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4002         r_cg_permutation_t *p;
4003         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4004         {
4005                 if (p->mode == mode && p->permutation == permutation)
4006                 {
4007                         //if (hashdepth > 10)
4008                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4009                         return p;
4010                 }
4011                 //hashdepth++;
4012         }
4013         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4014         p->mode = mode;
4015         p->permutation = permutation;
4016         p->hashnext = r_cg_permutationhash[mode][hashindex];
4017         r_cg_permutationhash[mode][hashindex] = p;
4018         //if (hashdepth > 10)
4019         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4020         return p;
4021 }
4022
4023 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4024 {
4025         char *shaderstring;
4026         if (!filename || !filename[0])
4027                 return NULL;
4028         if (!strcmp(filename, "cg/default.cg"))
4029         {
4030                 if (!cgshaderstring)
4031                 {
4032                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4033                         if (cgshaderstring)
4034                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4035                         else
4036                                 cgshaderstring = (char *)builtincgshaderstring;
4037                 }
4038                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4039                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4040                 return shaderstring;
4041         }
4042         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4043         if (shaderstring)
4044         {
4045                 if (printfromdisknotice)
4046                         Con_DPrintf("from disk %s... ", filename);
4047                 return shaderstring;
4048         }
4049         return shaderstring;
4050 }
4051
4052 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4053 {
4054         // TODO: load or create .fp and .vp shader files
4055 }
4056
4057 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4058 {
4059         int i;
4060         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4061         int vertstrings_count = 0, vertstring_length = 0;
4062         int geomstrings_count = 0, geomstring_length = 0;
4063         int fragstrings_count = 0, fragstring_length = 0;
4064         char *t;
4065         char *vertexstring, *geometrystring, *fragmentstring;
4066         char *vertstring, *geomstring, *fragstring;
4067         const char *vertstrings_list[32+3];
4068         const char *geomstrings_list[32+3];
4069         const char *fragstrings_list[32+3];
4070         char permutationname[256];
4071         char cachename[256];
4072         CGprofile vertexProfile;
4073         CGprofile fragmentProfile;
4074
4075         if (p->compiled)
4076                 return;
4077         p->compiled = true;
4078         p->vprogram = NULL;
4079         p->fprogram = NULL;
4080
4081         permutationname[0] = 0;
4082         cachename[0] = 0;
4083         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4084         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4085         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4086
4087         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4088         strlcat(cachename, "cg/", sizeof(cachename));
4089
4090         // the first pretext is which type of shader to compile as
4091         // (later these will all be bound together as a program object)
4092         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4093         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4094         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4095
4096         // the second pretext is the mode (for example a light source)
4097         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4098         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4099         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4100         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4101         strlcat(cachename, modeinfo->name, sizeof(cachename));
4102
4103         // now add all the permutation pretexts
4104         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4105         {
4106                 if (permutation & (1<<i))
4107                 {
4108                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4109                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4110                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4111                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4112                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4113                 }
4114                 else
4115                 {
4116                         // keep line numbers correct
4117                         vertstrings_list[vertstrings_count++] = "\n";
4118                         geomstrings_list[geomstrings_count++] = "\n";
4119                         fragstrings_list[fragstrings_count++] = "\n";
4120                 }
4121         }
4122
4123         // replace spaces in the cachename with _ characters
4124         for (i = 0;cachename[i];i++)
4125                 if (cachename[i] == ' ')
4126                         cachename[i] = '_';
4127
4128         // now append the shader text itself
4129         vertstrings_list[vertstrings_count++] = vertexstring;
4130         geomstrings_list[geomstrings_count++] = geometrystring;
4131         fragstrings_list[fragstrings_count++] = fragmentstring;
4132
4133         // if any sources were NULL, clear the respective list
4134         if (!vertexstring)
4135                 vertstrings_count = 0;
4136         if (!geometrystring)
4137                 geomstrings_count = 0;
4138         if (!fragmentstring)
4139                 fragstrings_count = 0;
4140
4141         vertstring_length = 0;
4142         for (i = 0;i < vertstrings_count;i++)
4143                 vertstring_length += strlen(vertstrings_list[i]);
4144         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4145         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4146                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4147
4148         geomstring_length = 0;
4149         for (i = 0;i < geomstrings_count;i++)
4150                 geomstring_length += strlen(geomstrings_list[i]);
4151         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4152         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4153                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4154
4155         fragstring_length = 0;
4156         for (i = 0;i < fragstrings_count;i++)
4157                 fragstring_length += strlen(fragstrings_list[i]);
4158         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4159         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4160                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4161
4162         CHECKGLERROR
4163         CHECKCGERROR
4164         //vertexProfile = CG_PROFILE_ARBVP1;
4165         //fragmentProfile = CG_PROFILE_ARBFP1;
4166         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4167         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4168         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4169         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4170         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4171         CHECKGLERROR
4172
4173         // try to load the cached shader, or generate one
4174         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4175
4176         // if caching failed, do a dynamic compile for now
4177         CHECKCGERROR
4178         if (vertstring[0] && !p->vprogram)
4179                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4180         CHECKCGERROR
4181         if (fragstring[0] && !p->fprogram)
4182                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4183         CHECKCGERROR
4184
4185         // look up all the uniform variable names we care about, so we don't
4186         // have to look them up every time we set them
4187         if (p->vprogram)
4188         {
4189                 CHECKCGERROR
4190                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4191                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4192                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4193                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4194                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4195                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4196                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4197                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4198                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4199                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4200                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4201                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4202                 CHECKCGERROR
4203         }
4204         if (p->fprogram)
4205         {
4206                 CHECKCGERROR
4207                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4208                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4209                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4210                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4211                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4212                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4213                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4214                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4215                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4216                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4217                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4218                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4219                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4220                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4221                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4222                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4223                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4224                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4225                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4226                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4227                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4228                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4229                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4230                 p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4231                 p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4232                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4233                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4234                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4235                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4236                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4237                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4238                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4239                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4240                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4241                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4242                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4243                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4244                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4245                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4246                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4247                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4248                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4249                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4250                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4251                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4252                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4253                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4254                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4255                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4256                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4257                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4258                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4259                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4260                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4261                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4262                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4263                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4264                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4265                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4266                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4267                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4268                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4269                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4270                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4271                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4272                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4273                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4274                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4275                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4276                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4277                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4278                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4279                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4280                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4281                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4282                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4283                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4284                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4285                 CHECKCGERROR
4286         }
4287
4288         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4289                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4290         else
4291                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4292
4293         // free the strings
4294         if (vertstring)
4295                 Mem_Free(vertstring);
4296         if (geomstring)
4297                 Mem_Free(geomstring);
4298         if (fragstring)
4299                 Mem_Free(fragstring);
4300         if (vertexstring)
4301                 Mem_Free(vertexstring);
4302         if (geometrystring)
4303                 Mem_Free(geometrystring);
4304         if (fragmentstring)
4305                 Mem_Free(fragmentstring);
4306 }
4307
4308 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4309 {
4310         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4311         CHECKGLERROR
4312         CHECKCGERROR
4313         if (r_cg_permutation != perm)
4314         {
4315                 r_cg_permutation = perm;
4316                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4317                 {
4318                         if (!r_cg_permutation->compiled)
4319                                 R_CG_CompilePermutation(perm, mode, permutation);
4320                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4321                         {
4322                                 // remove features until we find a valid permutation
4323                                 int i;
4324                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4325                                 {
4326                                         // reduce i more quickly whenever it would not remove any bits
4327                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4328                                         if (!(permutation & j))
4329                                                 continue;
4330                                         permutation -= j;
4331                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4332                                         if (!r_cg_permutation->compiled)
4333                                                 R_CG_CompilePermutation(perm, mode, permutation);
4334                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4335                                                 break;
4336                                 }
4337                                 if (i >= SHADERPERMUTATION_COUNT)
4338                                 {
4339                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4340                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4341                                         return; // no bit left to clear, entire mode is broken
4342                                 }
4343                         }
4344                 }
4345                 CHECKGLERROR
4346                 CHECKCGERROR
4347                 if (r_cg_permutation->vprogram)
4348                 {
4349                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4350                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4351                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4352                 }
4353                 else
4354                 {
4355                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4356                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4357                 }
4358                 if (r_cg_permutation->fprogram)
4359                 {
4360                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4361                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4362                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4363                 }
4364                 else
4365                 {
4366                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4367                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4368                 }
4369         }
4370         CHECKCGERROR
4371         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4372         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4373         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4374 }
4375
4376 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4377 {
4378         cgGLSetTextureParameter(param, R_GetTexture(tex));
4379         cgGLEnableTextureParameter(param);
4380 }
4381 #endif
4382
4383 void R_GLSL_Restart_f(void)
4384 {
4385         unsigned int i, limit;
4386         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4387                 Mem_Free(glslshaderstring);
4388         glslshaderstring = NULL;
4389         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4390                 Mem_Free(cgshaderstring);
4391         cgshaderstring = NULL;
4392         switch(vid.renderpath)
4393         {
4394         case RENDERPATH_GL20:
4395                 {
4396                         r_glsl_permutation_t *p;
4397                         r_glsl_permutation = NULL;
4398                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4399                         for (i = 0;i < limit;i++)
4400                         {
4401                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4402                                 {
4403                                         GL_Backend_FreeProgram(p->program);
4404                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4405                                 }
4406                         }
4407                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4408                 }
4409                 break;
4410         case RENDERPATH_CGGL:
4411 #ifdef SUPPORTCG
4412                 {
4413                         r_cg_permutation_t *p;
4414                         r_cg_permutation = NULL;
4415                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4416                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4417                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4418                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4419                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4420                         for (i = 0;i < limit;i++)
4421                         {
4422                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4423                                 {
4424                                         if (p->vprogram)
4425                                                 cgDestroyProgram(p->vprogram);
4426                                         if (p->fprogram)
4427                                                 cgDestroyProgram(p->fprogram);
4428                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4429                                 }
4430                         }
4431                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4432                 }
4433                 break;
4434 #endif
4435         case RENDERPATH_GL13:
4436         case RENDERPATH_GL11:
4437                 break;
4438         }
4439 }
4440
4441 void R_GLSL_DumpShader_f(void)
4442 {
4443         int i;
4444         qfile_t *file;
4445
4446         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4447         if (file)
4448         {
4449                 FS_Print(file, "/* The engine may define the following macros:\n");
4450                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4451                 for (i = 0;i < SHADERMODE_COUNT;i++)
4452                         FS_Print(file, glslshadermodeinfo[i].pretext);
4453                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4454                         FS_Print(file, shaderpermutationinfo[i].pretext);
4455                 FS_Print(file, "*/\n");
4456                 FS_Print(file, builtinshaderstring);
4457                 FS_Close(file);
4458                 Con_Printf("glsl/default.glsl written\n");
4459         }
4460         else
4461                 Con_Printf("failed to write to glsl/default.glsl\n");
4462
4463 #ifdef SUPPORTCG
4464         file = FS_OpenRealFile("cg/default.cg", "w", false);
4465         if (file)
4466         {
4467                 FS_Print(file, "/* The engine may define the following macros:\n");
4468                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4469                 for (i = 0;i < SHADERMODE_COUNT;i++)
4470                         FS_Print(file, cgshadermodeinfo[i].pretext);
4471                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4472                         FS_Print(file, shaderpermutationinfo[i].pretext);
4473                 FS_Print(file, "*/\n");
4474                 FS_Print(file, builtincgshaderstring);
4475                 FS_Close(file);
4476                 Con_Printf("cg/default.cg written\n");
4477         }
4478         else
4479                 Con_Printf("failed to write to cg/default.cg\n");
4480 #endif
4481 }
4482
4483 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4484 {
4485         if (!second)
4486                 texturemode = GL_MODULATE;
4487         switch (vid.renderpath)
4488         {
4489         case RENDERPATH_GL20:
4490                 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))));
4491                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4492                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4493                 break;
4494         case RENDERPATH_CGGL:
4495 #ifdef SUPPORTCG
4496                 CHECKCGERROR
4497                 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))));
4498                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4499                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4500 #endif
4501                 break;
4502         case RENDERPATH_GL13:
4503                 R_Mesh_TexBind(0, first );
4504                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4505                 R_Mesh_TexBind(1, second);
4506                 if (second)
4507                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4508                 break;
4509         case RENDERPATH_GL11:
4510                 R_Mesh_TexBind(0, first );
4511                 break;
4512         }
4513 }
4514
4515 void R_SetupShader_DepthOrShadow(void)
4516 {
4517         switch (vid.renderpath)
4518         {
4519         case RENDERPATH_GL20:
4520                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4521                 break;
4522         case RENDERPATH_CGGL:
4523 #ifdef SUPPORTCG
4524                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4525 #endif
4526                 break;
4527         case RENDERPATH_GL13:
4528                 R_Mesh_TexBind(0, 0);
4529                 R_Mesh_TexBind(1, 0);
4530                 break;
4531         case RENDERPATH_GL11:
4532                 R_Mesh_TexBind(0, 0);
4533                 break;
4534         }
4535 }
4536
4537 void R_SetupShader_ShowDepth(void)
4538 {
4539         switch (vid.renderpath)
4540         {
4541         case RENDERPATH_GL20:
4542                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4543                 break;
4544         case RENDERPATH_CGGL:
4545 #ifdef SUPPORTCG
4546                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4547 #endif
4548                 break;
4549         case RENDERPATH_GL13:
4550                 break;
4551         case RENDERPATH_GL11:
4552                 break;
4553         }
4554 }
4555
4556 extern qboolean r_shadow_usingdeferredprepass;
4557 extern cvar_t r_shadow_deferred_8bitrange;
4558 extern rtexture_t *r_shadow_attenuationgradienttexture;
4559 extern rtexture_t *r_shadow_attenuation2dtexture;
4560 extern rtexture_t *r_shadow_attenuation3dtexture;
4561 extern qboolean r_shadow_usingshadowmaprect;
4562 extern qboolean r_shadow_usingshadowmapcube;
4563 extern qboolean r_shadow_usingshadowmap2d;
4564 extern qboolean r_shadow_usingshadowmaportho;
4565 extern float r_shadow_shadowmap_texturescale[2];
4566 extern float r_shadow_shadowmap_parameters[4];
4567 extern qboolean r_shadow_shadowmapvsdct;
4568 extern qboolean r_shadow_shadowmapsampler;
4569 extern int r_shadow_shadowmappcf;
4570 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4571 extern rtexture_t *r_shadow_shadowmap2dtexture;
4572 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4573 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4574 extern matrix4x4_t r_shadow_shadowmapmatrix;
4575 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4576 extern int r_shadow_prepass_width;
4577 extern int r_shadow_prepass_height;
4578 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4579 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4580 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4581 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4582 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4583 {
4584         // select a permutation of the lighting shader appropriate to this
4585         // combination of texture, entity, light source, and fogging, only use the
4586         // minimum features necessary to avoid wasting rendering time in the
4587         // fragment shader on features that are not being used
4588         unsigned int permutation = 0;
4589         unsigned int mode = 0;
4590         float m16f[16];
4591         if (rsurfacepass == RSURFPASS_BACKGROUND)
4592         {
4593                 // distorted background
4594                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4595                         mode = SHADERMODE_WATER;
4596                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
4597                         mode = SHADERMODE_REFRACTION;
4598                 else
4599                 {
4600                         mode = SHADERMODE_GENERIC;
4601                         permutation |= SHADERPERMUTATION_DIFFUSE;
4602                 }
4603                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4604                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4605                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4606                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4607                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4608                 R_Mesh_ColorPointer(NULL, 0, 0);
4609                 GL_AlphaTest(false);
4610                 GL_BlendFunc(GL_ONE, GL_ZERO);
4611         }
4612         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4613         {
4614                 if (r_glsl_offsetmapping.integer)
4615                 {
4616                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4617                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4618                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4619                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4620                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4621                         {
4622                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4623                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4624                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4625                         }
4626                 }
4627                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4628                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4629                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4630                         permutation |= SHADERPERMUTATION_ALPHAKILL;
4631                 // normalmap (deferred prepass), may use alpha test on diffuse
4632                 mode = SHADERMODE_DEFERREDGEOMETRY;
4633                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4634                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4635                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4636                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4637                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4638                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4639                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4640                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4641                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4642                 else
4643                         R_Mesh_ColorPointer(NULL, 0, 0);
4644                 GL_AlphaTest(false);
4645                 GL_BlendFunc(GL_ONE, GL_ZERO);
4646         }
4647         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4648         {
4649                 if (r_glsl_offsetmapping.integer)
4650                 {
4651                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4652                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4653                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4654                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4655                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4656                         {
4657                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4658                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4659                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4660                         }
4661                 }
4662                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4663                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4664                 // light source
4665                 mode = SHADERMODE_LIGHTSOURCE;
4666                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4667                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4668                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4669                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4670                 if (diffusescale > 0)
4671                         permutation |= SHADERPERMUTATION_DIFFUSE;
4672                 if (specularscale > 0)
4673                 {
4674                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4675                         if (r_shadow_glossexact.integer)
4676                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4677                 }
4678                 if (r_refdef.fogenabled)
4679                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4680                 if (rsurface.texture->colormapping)
4681                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4682                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4683                 {
4684                         if (r_shadow_usingshadowmaprect)
4685                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4686                         if (r_shadow_usingshadowmap2d)
4687                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4688                         if (r_shadow_usingshadowmapcube)
4689                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4690                         else if(r_shadow_shadowmapvsdct)
4691                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4692
4693                         if (r_shadow_shadowmapsampler)
4694                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4695                         if (r_shadow_shadowmappcf > 1)
4696                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4697                         else if (r_shadow_shadowmappcf)
4698                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4699                 }
4700                 if (rsurface.texture->reflectmasktexture)
4701                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4702                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4703                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4704                 {
4705                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4706                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4707                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4708                 }
4709                 else
4710                 {
4711                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4712                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4713                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4714                 }
4715                 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4716                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4717                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4718                 else
4719                         R_Mesh_ColorPointer(NULL, 0, 0);
4720                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4721                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4722         }
4723         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4724         {
4725                 if (r_glsl_offsetmapping.integer)
4726                 {
4727                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4728                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4729                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4730                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4731                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4732                         {
4733                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4734                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4735                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4736                         }
4737                 }
4738                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4739                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4740                 // unshaded geometry (fullbright or ambient model lighting)
4741                 mode = SHADERMODE_FLATCOLOR;
4742                 ambientscale = diffusescale = specularscale = 0;
4743                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4744                         permutation |= SHADERPERMUTATION_GLOW;
4745                 if (r_refdef.fogenabled)
4746                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4747                 if (rsurface.texture->colormapping)
4748                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4749                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4750                 {
4751                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4752                         if (r_shadow_usingshadowmaprect)
4753                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4754                         if (r_shadow_usingshadowmap2d)
4755                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4756
4757                         if (r_shadow_shadowmapsampler)
4758                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4759                         if (r_shadow_shadowmappcf > 1)
4760                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4761                         else if (r_shadow_shadowmappcf)
4762                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4763                 }
4764                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4765                         permutation |= SHADERPERMUTATION_REFLECTION;
4766                 if (rsurface.texture->reflectmasktexture)
4767                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4768                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4769                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4770                 {
4771                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4772                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4773                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4774                 }
4775                 else
4776                 {
4777                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4778                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4779                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4780                 }
4781                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4782                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4783                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4784                 else
4785                         R_Mesh_ColorPointer(NULL, 0, 0);
4786                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4787                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4788         }
4789         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4790         {
4791                 if (r_glsl_offsetmapping.integer)
4792                 {
4793                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4794                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4795                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4796                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4797                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4798                         {
4799                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4800                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4801                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4802                         }
4803                 }
4804                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4805                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4806                 // directional model lighting
4807                 mode = SHADERMODE_LIGHTDIRECTION;
4808                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4809                         permutation |= SHADERPERMUTATION_GLOW;
4810                 permutation |= SHADERPERMUTATION_DIFFUSE;
4811                 if (specularscale > 0)
4812                 {
4813                         permutation |= SHADERPERMUTATION_SPECULAR;
4814                         if (r_shadow_glossexact.integer)
4815                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4816                 }
4817                 if (r_refdef.fogenabled)
4818                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4819                 if (rsurface.texture->colormapping)
4820                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4821                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4822                 {
4823                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4824                         if (r_shadow_usingshadowmaprect)
4825                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4826                         if (r_shadow_usingshadowmap2d)
4827                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4828
4829                         if (r_shadow_shadowmapsampler)
4830                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4831                         if (r_shadow_shadowmappcf > 1)
4832                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4833                         else if (r_shadow_shadowmappcf)
4834                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4835                 }
4836                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4837                         permutation |= SHADERPERMUTATION_REFLECTION;
4838                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4839                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4840                 if (rsurface.texture->reflectmasktexture)
4841                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4842                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4843                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4844                 {
4845                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4846                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4847                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4848                 }
4849                 else
4850                 {
4851                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4852                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4853                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4854                 }
4855                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4856                 R_Mesh_ColorPointer(NULL, 0, 0);
4857                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4858                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4859         }
4860         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4861         {
4862                 if (r_glsl_offsetmapping.integer)
4863                 {
4864                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4865                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4866                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4867                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4868                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4869                         {
4870                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4871                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4872                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4873                         }
4874                 }
4875                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4876                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4877                 // ambient model lighting
4878                 mode = SHADERMODE_LIGHTDIRECTION;
4879                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4880                         permutation |= SHADERPERMUTATION_GLOW;
4881                 if (r_refdef.fogenabled)
4882                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4883                 if (rsurface.texture->colormapping)
4884                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4885                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4886                 {
4887                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4888                         if (r_shadow_usingshadowmaprect)
4889                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4890                         if (r_shadow_usingshadowmap2d)
4891                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4892
4893                         if (r_shadow_shadowmapsampler)
4894                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4895                         if (r_shadow_shadowmappcf > 1)
4896                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4897                         else if (r_shadow_shadowmappcf)
4898                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4899                 }
4900                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4901                         permutation |= SHADERPERMUTATION_REFLECTION;
4902                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4903                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4904                 if (rsurface.texture->reflectmasktexture)
4905                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4906                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4907                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4908                 {
4909                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4910                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4911                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4912                 }
4913                 else
4914                 {
4915                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4916                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4917                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4918                 }
4919                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4920                 R_Mesh_ColorPointer(NULL, 0, 0);
4921                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4922                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4923         }
4924         else
4925         {
4926                 if (r_glsl_offsetmapping.integer)
4927                 {
4928                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4929                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4930                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4931                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4932                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4933                         {
4934                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4935                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4936                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4937                         }
4938                 }
4939                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4940                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4941                 // lightmapped wall
4942                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4943                         permutation |= SHADERPERMUTATION_GLOW;
4944                 if (r_refdef.fogenabled)
4945                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4946                 if (rsurface.texture->colormapping)
4947                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4948                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4949                 {
4950                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4951                         if (r_shadow_usingshadowmaprect)
4952                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4953                         if (r_shadow_usingshadowmap2d)
4954                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4955
4956                         if (r_shadow_shadowmapsampler)
4957                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4958                         if (r_shadow_shadowmappcf > 1)
4959                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4960                         else if (r_shadow_shadowmappcf)
4961                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4962                 }
4963                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4964                         permutation |= SHADERPERMUTATION_REFLECTION;
4965                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4966                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4967                 if (rsurface.texture->reflectmasktexture)
4968                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4969                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4970                 {
4971                         // deluxemapping (light direction texture)
4972                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4973                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4974                         else
4975                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4976                         permutation |= SHADERPERMUTATION_DIFFUSE;
4977                         if (specularscale > 0)
4978                         {
4979                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4980                                 if (r_shadow_glossexact.integer)
4981                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4982                         }
4983                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4984                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4985                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4986                         else
4987                                 R_Mesh_ColorPointer(NULL, 0, 0);
4988                 }
4989                 else if (r_glsl_deluxemapping.integer >= 2)
4990                 {
4991                         // fake deluxemapping (uniform light direction in tangentspace)
4992                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4993                         permutation |= SHADERPERMUTATION_DIFFUSE;
4994                         if (specularscale > 0)
4995                         {
4996                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4997                                 if (r_shadow_glossexact.integer)
4998                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4999                         }
5000                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5001                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
5002                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5003                         else
5004                                 R_Mesh_ColorPointer(NULL, 0, 0);
5005                 }
5006                 else if (rsurface.uselightmaptexture)
5007                 {
5008                         // ordinary lightmapping (q1bsp, q3bsp)
5009                         mode = SHADERMODE_LIGHTMAP;
5010                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5011                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
5012                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5013                         else
5014                                 R_Mesh_ColorPointer(NULL, 0, 0);
5015                 }
5016                 else
5017                 {
5018                         // ordinary vertex coloring (q3bsp)
5019                         mode = SHADERMODE_VERTEXCOLOR;
5020                         R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
5021                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5022                 }
5023                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5024                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
5025                 {
5026                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5027                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5028                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5029                 }
5030                 else
5031                 {
5032                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
5033                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
5034                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
5035                 }
5036                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5037                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5038         }
5039         switch(vid.renderpath)
5040         {
5041         case RENDERPATH_GL20:
5042                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5043                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5044                 if (mode == SHADERMODE_LIGHTSOURCE)
5045                 {
5046                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5047                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5048                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5049                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0] * ambientscale, rsurface.colormod[1] * ambientscale, rsurface.colormod[2] * ambientscale);
5050                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.colormod[0] * diffusescale, rsurface.colormod[1] * diffusescale, rsurface.colormod[2] * diffusescale);
5051                         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);
5052         
5053                         // additive passes are only darkened by fog, not tinted
5054                         if (r_glsl_permutation->loc_FogColor >= 0)
5055                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5056                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5057                 }
5058                 else
5059                 {
5060                         if (mode == SHADERMODE_FLATCOLOR)
5061                         {
5062                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
5063                         }
5064                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5065                         {
5066                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * rsurface.colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * rsurface.colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * rsurface.colormod[2]);
5067                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.colormod[2]);
5068                                 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);
5069                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, rsurface.colormod[0] * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * r_shadow_deferred_8bitrange.value);
5070                                 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);
5071                                 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]);
5072                                 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]);
5073                         }
5074                         else
5075                         {
5076                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * rsurface.colormod[0], r_refdef.scene.ambient * rsurface.colormod[1], r_refdef.scene.ambient * rsurface.colormod[2]);
5077                                 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]);
5078                                 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);
5079                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, rsurface.colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5080                                 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);
5081                         }
5082                         // additive passes are only darkened by fog, not tinted
5083                         if (r_glsl_permutation->loc_FogColor >= 0)
5084                         {
5085                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5086                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5087                                 else
5088                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5089                         }
5090                         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);
5091                         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]);
5092                         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]);
5093                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
5094                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
5095                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5096                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5097                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5098                 }
5099                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5100                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5101                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5102                 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]);
5103                 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]);
5104
5105                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5106                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
5107                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5108                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5109                 {
5110                         if (rsurface.texture->pantstexture)
5111                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5112                         else
5113                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5114                 }
5115                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5116                 {
5117                         if (rsurface.texture->shirttexture)
5118                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5119                         else
5120                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5121                 }
5122                 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]);
5123                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5124                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5125                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5126                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5127                 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]);
5128                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5129
5130         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5131         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5132         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5133                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5134                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5135                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5136                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5137                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5138                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5139                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5140                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5141                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5142                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5143                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5144                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5145                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5146                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5147                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
5148                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_blanknormalmap                            );
5149                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5150                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
5151                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
5152                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5153                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5154                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5155                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5156                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5157                 {
5158                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5159                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture                  );
5160                         if (rsurface.rtlight)
5161                         {
5162                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5163                                 if (r_shadow_usingshadowmapcube)
5164                                         if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5165                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5166                         }
5167                 }
5168                 CHECKGLERROR
5169                 break;
5170         case RENDERPATH_CGGL:
5171 #ifdef SUPPORTCG
5172                 R_SetupShader_SetPermutationCG(mode, permutation);
5173                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5174                 if (mode == SHADERMODE_LIGHTSOURCE)
5175                 {
5176                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5177                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5178                 }
5179                 else
5180                 {
5181                         if (mode == SHADERMODE_LIGHTDIRECTION)
5182                         {
5183                                 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
5184                         }
5185                 }
5186                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5187                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5188                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5189                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5190                 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
5191                 CHECKGLERROR
5192
5193                 if (mode == SHADERMODE_LIGHTSOURCE)
5194                 {
5195                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5196                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5197                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0] * ambientscale, rsurface.colormod[1] * ambientscale, rsurface.colormod[2] * ambientscale);CHECKCGERROR
5198                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.colormod[0] * diffusescale, rsurface.colormod[1] * diffusescale, rsurface.colormod[2] * diffusescale);CHECKCGERROR
5199                         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
5200
5201                         // additive passes are only darkened by fog, not tinted
5202                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5203                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5204                 }
5205                 else
5206                 {
5207                         if (mode == SHADERMODE_FLATCOLOR)
5208                         {
5209                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
5210                         }
5211                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5212                         {
5213                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * rsurface.colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * rsurface.colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * rsurface.colormod[2]);CHECKCGERROR
5214                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.colormod[2]);CHECKCGERROR
5215                                 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
5216                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, rsurface.colormod[0] * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * r_shadow_deferred_8bitrange.value);CHECKCGERROR
5217                                 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
5218                                 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
5219                                 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
5220                         }
5221                         else
5222                         {
5223                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, r_refdef.scene.ambient * rsurface.colormod[0], r_refdef.scene.ambient * rsurface.colormod[1], r_refdef.scene.ambient * rsurface.colormod[2]);CHECKCGERROR
5224                                 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
5225                                 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
5226                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, rsurface.colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
5227                                 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
5228                         }
5229                         // additive passes are only darkened by fog, not tinted
5230                         if (r_cg_permutation->fp_FogColor)
5231                         {
5232                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5233                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5234                                 else
5235                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5236                                 CHECKCGERROR
5237                         }
5238                         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
5239                         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
5240                         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
5241                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5242                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5243                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5244                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5245                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5246                 }
5247                 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
5248                 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
5249                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5250                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5251                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5252                 if (r_cg_permutation->fp_Color_Pants)
5253                 {
5254                         if (rsurface.texture->pantstexture)
5255                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5256                         else
5257                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5258                         CHECKCGERROR
5259                 }
5260                 if (r_cg_permutation->fp_Color_Shirt)
5261                 {
5262                         if (rsurface.texture->shirttexture)
5263                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5264                         else
5265                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5266                         CHECKCGERROR
5267                 }
5268                 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
5269                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5270                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5271                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5272                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5273                 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
5274                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5275
5276         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
5277         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
5278         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
5279                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
5280                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
5281                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
5282                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
5283                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
5284                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
5285                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
5286                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
5287                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
5288                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
5289                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
5290                 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
5291                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
5292                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
5293                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
5294                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
5295                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5296                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
5297                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
5298                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5299                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5300                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
5301                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
5302                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5303                 {
5304                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5305                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5306                         if (rsurface.rtlight)
5307                         {
5308                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5309                                 if (r_shadow_usingshadowmapcube)
5310                                         if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5311                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5312                         }
5313                 }
5314
5315                 CHECKGLERROR
5316 #endif
5317                 break;
5318         case RENDERPATH_GL13:
5319         case RENDERPATH_GL11:
5320                 break;
5321         }
5322 }
5323
5324 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5325 {
5326         // select a permutation of the lighting shader appropriate to this
5327         // combination of texture, entity, light source, and fogging, only use the
5328         // minimum features necessary to avoid wasting rendering time in the
5329         // fragment shader on features that are not being used
5330         unsigned int permutation = 0;
5331         unsigned int mode = 0;
5332         const float *lightcolorbase = rtlight->currentcolor;
5333         float ambientscale = rtlight->ambientscale;
5334         float diffusescale = rtlight->diffusescale;
5335         float specularscale = rtlight->specularscale;
5336         // this is the location of the light in view space
5337         vec3_t viewlightorigin;
5338         // this transforms from view space (camera) to light space (cubemap)
5339         matrix4x4_t viewtolight;
5340         matrix4x4_t lighttoview;
5341         float viewtolight16f[16];
5342         float range = 1.0f / r_shadow_deferred_8bitrange.value;
5343         // light source
5344         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5345         if (rtlight->currentcubemap != r_texture_whitecube)
5346                 permutation |= SHADERPERMUTATION_CUBEFILTER;
5347         if (diffusescale > 0)
5348                 permutation |= SHADERPERMUTATION_DIFFUSE;
5349         if (specularscale > 0)
5350         {
5351                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5352                 if (r_shadow_glossexact.integer)
5353                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5354         }
5355         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5356         {
5357                 if (r_shadow_usingshadowmaprect)
5358                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5359                 if (r_shadow_usingshadowmap2d)
5360                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5361                 if (r_shadow_usingshadowmapcube)
5362                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5363                 else if(r_shadow_shadowmapvsdct)
5364                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5365
5366                 if (r_shadow_shadowmapsampler)
5367                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5368                 if (r_shadow_shadowmappcf > 1)
5369                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5370                 else if (r_shadow_shadowmappcf)
5371                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5372         }
5373         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5374         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5375         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5376         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5377         switch(vid.renderpath)
5378         {
5379         case RENDERPATH_GL20:
5380                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5381                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5382                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
5383                 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);
5384                 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);
5385                 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);
5386                 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]);
5387                 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]);
5388                 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));
5389                 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]);
5390                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5391
5392                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5393                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5394                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5395                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5396                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
5397                 if (r_shadow_usingshadowmapcube)
5398                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5399                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
5400                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5401                 break;
5402         case RENDERPATH_CGGL:
5403 #ifdef SUPPORTCG
5404                 R_SetupShader_SetPermutationCG(mode, permutation);
5405                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5406                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5407                 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
5408                 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
5409                 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
5410                 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
5411                 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
5412                 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
5413                 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
5414                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5415
5416                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5417                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5418                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5419                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5420                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5421                 if (r_shadow_usingshadowmapcube)
5422                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5423                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5424                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5425 #endif
5426                 break;
5427         case RENDERPATH_GL13:
5428         case RENDERPATH_GL11:
5429                 break;
5430         }
5431 }
5432
5433 #define SKINFRAME_HASH 1024
5434
5435 typedef struct
5436 {
5437         int loadsequence; // incremented each level change
5438         memexpandablearray_t array;
5439         skinframe_t *hash[SKINFRAME_HASH];
5440 }
5441 r_skinframe_t;
5442 r_skinframe_t r_skinframe;
5443
5444 void R_SkinFrame_PrepareForPurge(void)
5445 {
5446         r_skinframe.loadsequence++;
5447         // wrap it without hitting zero
5448         if (r_skinframe.loadsequence >= 200)
5449                 r_skinframe.loadsequence = 1;
5450 }
5451
5452 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5453 {
5454         if (!skinframe)
5455                 return;
5456         // mark the skinframe as used for the purging code
5457         skinframe->loadsequence = r_skinframe.loadsequence;
5458 }
5459
5460 void R_SkinFrame_Purge(void)
5461 {
5462         int i;
5463         skinframe_t *s;
5464         for (i = 0;i < SKINFRAME_HASH;i++)
5465         {
5466                 for (s = r_skinframe.hash[i];s;s = s->next)
5467                 {
5468                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5469                         {
5470                                 if (s->merged == s->base)
5471                                         s->merged = NULL;
5472                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5473                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5474                                 R_PurgeTexture(s->merged);s->merged = NULL;
5475                                 R_PurgeTexture(s->base  );s->base   = NULL;
5476                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5477                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5478                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5479                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5480                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5481                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5482                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
5483                                 s->loadsequence = 0;
5484                         }
5485                 }
5486         }
5487 }
5488
5489 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5490         skinframe_t *item;
5491         char basename[MAX_QPATH];
5492
5493         Image_StripImageExtension(name, basename, sizeof(basename));
5494
5495         if( last == NULL ) {
5496                 int hashindex;
5497                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5498                 item = r_skinframe.hash[hashindex];
5499         } else {
5500                 item = last->next;
5501         }
5502
5503         // linearly search through the hash bucket
5504         for( ; item ; item = item->next ) {
5505                 if( !strcmp( item->basename, basename ) ) {
5506                         return item;
5507                 }
5508         }
5509         return NULL;
5510 }
5511
5512 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5513 {
5514         skinframe_t *item;
5515         int hashindex;
5516         char basename[MAX_QPATH];
5517
5518         Image_StripImageExtension(name, basename, sizeof(basename));
5519
5520         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5521         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5522                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5523                         break;
5524
5525         if (!item) {
5526                 rtexture_t *dyntexture;
5527                 // check whether its a dynamic texture
5528                 dyntexture = CL_GetDynTexture( basename );
5529                 if (!add && !dyntexture)
5530                         return NULL;
5531                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5532                 memset(item, 0, sizeof(*item));
5533                 strlcpy(item->basename, basename, sizeof(item->basename));
5534                 item->base = dyntexture; // either NULL or dyntexture handle
5535                 item->textureflags = textureflags;
5536                 item->comparewidth = comparewidth;
5537                 item->compareheight = compareheight;
5538                 item->comparecrc = comparecrc;
5539                 item->next = r_skinframe.hash[hashindex];
5540                 r_skinframe.hash[hashindex] = item;
5541         }
5542         else if( item->base == NULL )
5543         {
5544                 rtexture_t *dyntexture;
5545                 // check whether its a dynamic texture
5546                 // 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]
5547                 dyntexture = CL_GetDynTexture( basename );
5548                 item->base = dyntexture; // either NULL or dyntexture handle
5549         }
5550
5551         R_SkinFrame_MarkUsed(item);
5552         return item;
5553 }
5554
5555 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5556         { \
5557                 unsigned long long avgcolor[5], wsum; \
5558                 int pix, comp, w; \
5559                 avgcolor[0] = 0; \
5560                 avgcolor[1] = 0; \
5561                 avgcolor[2] = 0; \
5562                 avgcolor[3] = 0; \
5563                 avgcolor[4] = 0; \
5564                 wsum = 0; \
5565                 for(pix = 0; pix < cnt; ++pix) \
5566                 { \
5567                         w = 0; \
5568                         for(comp = 0; comp < 3; ++comp) \
5569                                 w += getpixel; \
5570                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5571                         { \
5572                                 ++wsum; \
5573                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5574                                 w = getpixel; \
5575                                 for(comp = 0; comp < 3; ++comp) \
5576                                         avgcolor[comp] += getpixel * w; \
5577                                 avgcolor[3] += w; \
5578                         } \
5579                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5580                         avgcolor[4] += getpixel; \
5581                 } \
5582                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5583                         avgcolor[3] = 1; \
5584                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5585                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5586                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5587                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5588         }
5589
5590 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5591 {
5592         int j;
5593         unsigned char *pixels;
5594         unsigned char *bumppixels;
5595         unsigned char *basepixels = NULL;
5596         int basepixels_width = 0;
5597         int basepixels_height = 0;
5598         skinframe_t *skinframe;
5599         rtexture_t *ddsbase = NULL;
5600         qboolean ddshasalpha = false;
5601         float ddsavgcolor[4];
5602         char basename[MAX_QPATH];
5603
5604         if (cls.state == ca_dedicated)
5605                 return NULL;
5606
5607         // return an existing skinframe if already loaded
5608         // if loading of the first image fails, don't make a new skinframe as it
5609         // would cause all future lookups of this to be missing
5610         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5611         if (skinframe && skinframe->base)
5612                 return skinframe;
5613
5614         Image_StripImageExtension(name, basename, sizeof(basename));
5615
5616         // check for DDS texture file first
5617         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5618         {
5619                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer);
5620                 if (basepixels == NULL)
5621                         return NULL;
5622         }
5623
5624         if (developer_loading.integer)
5625                 Con_Printf("loading skin \"%s\"\n", name);
5626
5627         // we've got some pixels to store, so really allocate this new texture now
5628         if (!skinframe)
5629                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5630         skinframe->stain = NULL;
5631         skinframe->merged = NULL;
5632         skinframe->base = NULL;
5633         skinframe->pants = NULL;
5634         skinframe->shirt = NULL;
5635         skinframe->nmap = NULL;
5636         skinframe->gloss = NULL;
5637         skinframe->glow = NULL;
5638         skinframe->fog = NULL;
5639         skinframe->reflect = NULL;
5640         skinframe->hasalpha = false;
5641
5642         if (ddsbase)
5643         {
5644                 skinframe->base = ddsbase;
5645                 skinframe->hasalpha = ddshasalpha;
5646                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5647                 if (r_loadfog && skinframe->hasalpha)
5648                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5649                 //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]);
5650         }
5651         else
5652         {
5653                 basepixels_width = image_width;
5654                 basepixels_height = image_height;
5655                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5656                 if (textureflags & TEXF_ALPHA)
5657                 {
5658                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5659                         {
5660                                 if (basepixels[j] < 255)
5661                                 {
5662                                         skinframe->hasalpha = true;
5663                                         break;
5664                                 }
5665                         }
5666                         if (r_loadfog && skinframe->hasalpha)
5667                         {
5668                                 // has transparent pixels
5669                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5670                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5671                                 {
5672                                         pixels[j+0] = 255;
5673                                         pixels[j+1] = 255;
5674                                         pixels[j+2] = 255;
5675                                         pixels[j+3] = basepixels[j+3];
5676                                 }
5677                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5678                                 Mem_Free(pixels);
5679                         }
5680                 }
5681                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5682                 //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]);
5683                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5684                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5685                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5686                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5687         }
5688
5689         if (r_loaddds)
5690         {
5691                 if (r_loadnormalmap)
5692                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5693                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5694                 if (r_loadgloss)
5695                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5696                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5697                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5698                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL);
5699         }
5700
5701         // _norm is the name used by tenebrae and has been adopted as standard
5702         if (r_loadnormalmap && skinframe->nmap == NULL)
5703         {
5704                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false)) != NULL)
5705                 {
5706                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5707                         Mem_Free(pixels);
5708                         pixels = NULL;
5709                 }
5710                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false)) != NULL)
5711                 {
5712                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5713                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5714                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5715                         Mem_Free(pixels);
5716                         Mem_Free(bumppixels);
5717                 }
5718                 else if (r_shadow_bumpscale_basetexture.value > 0)
5719                 {
5720                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5721                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5722                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | skinframe->textureflags) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5723                         Mem_Free(pixels);
5724                 }
5725                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5726                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5727         }
5728
5729         // _luma is supported only for tenebrae compatibility
5730         // _glow is the preferred name
5731         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer))))
5732         {
5733                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5734                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5735                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5736                 Mem_Free(pixels);pixels = NULL;
5737         }
5738
5739         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5740         {
5741                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5742                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5743                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5744                 Mem_Free(pixels);
5745                 pixels = NULL;
5746         }
5747
5748         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5749         {
5750                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5751                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5752                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5753                 Mem_Free(pixels);
5754                 pixels = NULL;
5755         }
5756
5757         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5758         {
5759                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5760                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5761                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5762                 Mem_Free(pixels);
5763                 pixels = NULL;
5764         }
5765
5766         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5767         {
5768                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5769                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
5770                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true);
5771                 Mem_Free(pixels);
5772                 pixels = NULL;
5773         }
5774
5775         if (basepixels)
5776                 Mem_Free(basepixels);
5777
5778         return skinframe;
5779 }
5780
5781 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5782 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5783 {
5784         int i;
5785         unsigned char *temp1, *temp2;
5786         skinframe_t *skinframe;
5787
5788         if (cls.state == ca_dedicated)
5789                 return NULL;
5790
5791         // if already loaded just return it, otherwise make a new skinframe
5792         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5793         if (skinframe && skinframe->base)
5794                 return skinframe;
5795
5796         skinframe->stain = NULL;
5797         skinframe->merged = NULL;
5798         skinframe->base = NULL;
5799         skinframe->pants = NULL;
5800         skinframe->shirt = NULL;
5801         skinframe->nmap = NULL;
5802         skinframe->gloss = NULL;
5803         skinframe->glow = NULL;
5804         skinframe->fog = NULL;
5805         skinframe->reflect = NULL;
5806         skinframe->hasalpha = false;
5807
5808         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5809         if (!skindata)
5810                 return NULL;
5811
5812         if (developer_loading.integer)
5813                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5814
5815         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5816         {
5817                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5818                 temp2 = temp1 + width * height * 4;
5819                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5820                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5821                 Mem_Free(temp1);
5822         }
5823         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5824         if (textureflags & TEXF_ALPHA)
5825         {
5826                 for (i = 3;i < width * height * 4;i += 4)
5827                 {
5828                         if (skindata[i] < 255)
5829                         {
5830                                 skinframe->hasalpha = true;
5831                                 break;
5832                         }
5833                 }
5834                 if (r_loadfog && skinframe->hasalpha)
5835                 {
5836                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5837                         memcpy(fogpixels, skindata, width * height * 4);
5838                         for (i = 0;i < width * height * 4;i += 4)
5839                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5840                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5841                         Mem_Free(fogpixels);
5842                 }
5843         }
5844
5845         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5846         //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]);
5847
5848         return skinframe;
5849 }
5850
5851 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5852 {
5853         int i;
5854         int featuresmask;
5855         skinframe_t *skinframe;
5856
5857         if (cls.state == ca_dedicated)
5858                 return NULL;
5859
5860         // if already loaded just return it, otherwise make a new skinframe
5861         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5862         if (skinframe && skinframe->base)
5863                 return skinframe;
5864
5865         skinframe->stain = NULL;
5866         skinframe->merged = NULL;
5867         skinframe->base = NULL;
5868         skinframe->pants = NULL;
5869         skinframe->shirt = NULL;
5870         skinframe->nmap = NULL;
5871         skinframe->gloss = NULL;
5872         skinframe->glow = NULL;
5873         skinframe->fog = NULL;
5874         skinframe->reflect = NULL;
5875         skinframe->hasalpha = false;
5876
5877         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5878         if (!skindata)
5879                 return NULL;
5880
5881         if (developer_loading.integer)
5882                 Con_Printf("loading quake skin \"%s\"\n", name);
5883
5884         // 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)
5885         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5886         memcpy(skinframe->qpixels, skindata, width*height);
5887         skinframe->qwidth = width;
5888         skinframe->qheight = height;
5889
5890         featuresmask = 0;
5891         for (i = 0;i < width * height;i++)
5892                 featuresmask |= palette_featureflags[skindata[i]];
5893
5894         skinframe->hasalpha = false;
5895         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5896         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5897         skinframe->qgeneratemerged = true;
5898         skinframe->qgeneratebase = skinframe->qhascolormapping;
5899         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5900
5901         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5902         //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]);
5903
5904         return skinframe;
5905 }
5906
5907 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5908 {
5909         int width;
5910         int height;
5911         unsigned char *skindata;
5912
5913         if (!skinframe->qpixels)
5914                 return;
5915
5916         if (!skinframe->qhascolormapping)
5917                 colormapped = false;
5918
5919         if (colormapped)
5920         {
5921                 if (!skinframe->qgeneratebase)
5922                         return;
5923         }
5924         else
5925         {
5926                 if (!skinframe->qgeneratemerged)
5927                         return;
5928         }
5929
5930         width = skinframe->qwidth;
5931         height = skinframe->qheight;
5932         skindata = skinframe->qpixels;
5933
5934         if (skinframe->qgeneratenmap)
5935         {
5936                 unsigned char *temp1, *temp2;
5937                 skinframe->qgeneratenmap = false;
5938                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5939                 temp2 = temp1 + width * height * 4;
5940                 // use either a custom palette or the quake palette
5941                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5942                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5943                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5944                 Mem_Free(temp1);
5945         }
5946
5947         if (skinframe->qgenerateglow)
5948         {
5949                 skinframe->qgenerateglow = false;
5950                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5951         }
5952
5953         if (colormapped)
5954         {
5955                 skinframe->qgeneratebase = false;
5956                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
5957                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5958                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5959         }
5960         else
5961         {
5962                 skinframe->qgeneratemerged = false;
5963                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5964         }
5965
5966         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5967         {
5968                 Mem_Free(skinframe->qpixels);
5969                 skinframe->qpixels = NULL;
5970         }
5971 }
5972
5973 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)
5974 {
5975         int i;
5976         skinframe_t *skinframe;
5977
5978         if (cls.state == ca_dedicated)
5979                 return NULL;
5980
5981         // if already loaded just return it, otherwise make a new skinframe
5982         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5983         if (skinframe && skinframe->base)
5984                 return skinframe;
5985
5986         skinframe->stain = NULL;
5987         skinframe->merged = NULL;
5988         skinframe->base = NULL;
5989         skinframe->pants = NULL;
5990         skinframe->shirt = NULL;
5991         skinframe->nmap = NULL;
5992         skinframe->gloss = NULL;
5993         skinframe->glow = NULL;
5994         skinframe->fog = NULL;
5995         skinframe->reflect = NULL;
5996         skinframe->hasalpha = false;
5997
5998         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5999         if (!skindata)
6000                 return NULL;
6001
6002         if (developer_loading.integer)
6003                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6004
6005         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
6006         if (textureflags & TEXF_ALPHA)
6007         {
6008                 for (i = 0;i < width * height;i++)
6009                 {
6010                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6011                         {
6012                                 skinframe->hasalpha = true;
6013                                 break;
6014                         }
6015                 }
6016                 if (r_loadfog && skinframe->hasalpha)
6017                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
6018         }
6019
6020         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6021         //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]);
6022
6023         return skinframe;
6024 }
6025
6026 skinframe_t *R_SkinFrame_LoadMissing(void)
6027 {
6028         skinframe_t *skinframe;
6029
6030         if (cls.state == ca_dedicated)
6031                 return NULL;
6032
6033         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6034         skinframe->stain = NULL;
6035         skinframe->merged = NULL;
6036         skinframe->base = NULL;
6037         skinframe->pants = NULL;
6038         skinframe->shirt = NULL;
6039         skinframe->nmap = NULL;
6040         skinframe->gloss = NULL;
6041         skinframe->glow = NULL;
6042         skinframe->fog = NULL;
6043         skinframe->reflect = NULL;
6044         skinframe->hasalpha = false;
6045
6046         skinframe->avgcolor[0] = rand() / RAND_MAX;
6047         skinframe->avgcolor[1] = rand() / RAND_MAX;
6048         skinframe->avgcolor[2] = rand() / RAND_MAX;
6049         skinframe->avgcolor[3] = 1;
6050
6051         return skinframe;
6052 }
6053
6054 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6055 typedef struct suffixinfo_s
6056 {
6057         char *suffix;
6058         qboolean flipx, flipy, flipdiagonal;
6059 }
6060 suffixinfo_t;
6061 static suffixinfo_t suffix[3][6] =
6062 {
6063         {
6064                 {"px",   false, false, false},
6065                 {"nx",   false, false, false},
6066                 {"py",   false, false, false},
6067                 {"ny",   false, false, false},
6068                 {"pz",   false, false, false},
6069                 {"nz",   false, false, false}
6070         },
6071         {
6072                 {"posx", false, false, false},
6073                 {"negx", false, false, false},
6074                 {"posy", false, false, false},
6075                 {"negy", false, false, false},
6076                 {"posz", false, false, false},
6077                 {"negz", false, false, false}
6078         },
6079         {
6080                 {"rt",    true, false,  true},
6081                 {"lf",   false,  true,  true},
6082                 {"ft",    true,  true, false},
6083                 {"bk",   false, false, false},
6084                 {"up",    true, false,  true},
6085                 {"dn",    true, false,  true}
6086         }
6087 };
6088
6089 static int componentorder[4] = {0, 1, 2, 3};
6090
6091 rtexture_t *R_LoadCubemap(const char *basename)
6092 {
6093         int i, j, cubemapsize;
6094         unsigned char *cubemappixels, *image_buffer;
6095         rtexture_t *cubemaptexture;
6096         char name[256];
6097         // must start 0 so the first loadimagepixels has no requested width/height
6098         cubemapsize = 0;
6099         cubemappixels = NULL;
6100         cubemaptexture = NULL;
6101         // keep trying different suffix groups (posx, px, rt) until one loads
6102         for (j = 0;j < 3 && !cubemappixels;j++)
6103         {
6104                 // load the 6 images in the suffix group
6105                 for (i = 0;i < 6;i++)
6106                 {
6107                         // generate an image name based on the base and and suffix
6108                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6109                         // load it
6110                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer)))
6111                         {
6112                                 // an image loaded, make sure width and height are equal
6113                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6114                                 {
6115                                         // if this is the first image to load successfully, allocate the cubemap memory
6116                                         if (!cubemappixels && image_width >= 1)
6117                                         {
6118                                                 cubemapsize = image_width;
6119                                                 // note this clears to black, so unavailable sides are black
6120                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6121                                         }
6122                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6123                                         if (cubemappixels)
6124                                                 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);
6125                                 }
6126                                 else
6127                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6128                                 // free the image
6129                                 Mem_Free(image_buffer);
6130                         }
6131                 }
6132         }
6133         // if a cubemap loaded, upload it
6134         if (cubemappixels)
6135         {
6136                 if (developer_loading.integer)
6137                         Con_Printf("loading cubemap \"%s\"\n", basename);
6138
6139                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR, NULL);
6140                 Mem_Free(cubemappixels);
6141         }
6142         else
6143         {
6144                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6145                 if (developer_loading.integer)
6146                 {
6147                         Con_Printf("(tried tried images ");
6148                         for (j = 0;j < 3;j++)
6149                                 for (i = 0;i < 6;i++)
6150                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6151                         Con_Print(" and was unable to find any of them).\n");
6152                 }
6153         }
6154         return cubemaptexture;
6155 }
6156
6157 rtexture_t *R_GetCubemap(const char *basename)
6158 {
6159         int i;
6160         for (i = 0;i < r_texture_numcubemaps;i++)
6161                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6162                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6163         if (i >= MAX_CUBEMAPS)
6164                 return r_texture_whitecube;
6165         r_texture_numcubemaps++;
6166         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6167         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6168         return r_texture_cubemaps[i].texture;
6169 }
6170
6171 void R_FreeCubemaps(void)
6172 {
6173         int i;
6174         for (i = 0;i < r_texture_numcubemaps;i++)
6175         {
6176                 if (developer_loading.integer)
6177                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6178                 if (r_texture_cubemaps[i].texture)
6179                         R_FreeTexture(r_texture_cubemaps[i].texture);
6180         }
6181         r_texture_numcubemaps = 0;
6182 }
6183
6184 void R_Main_FreeViewCache(void)
6185 {
6186         if (r_refdef.viewcache.entityvisible)
6187                 Mem_Free(r_refdef.viewcache.entityvisible);
6188         if (r_refdef.viewcache.world_pvsbits)
6189                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6190         if (r_refdef.viewcache.world_leafvisible)
6191                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6192         if (r_refdef.viewcache.world_surfacevisible)
6193                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6194         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6195 }
6196
6197 void R_Main_ResizeViewCache(void)
6198 {
6199         int numentities = r_refdef.scene.numentities;
6200         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6201         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6202         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6203         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6204         if (r_refdef.viewcache.maxentities < numentities)
6205         {
6206                 r_refdef.viewcache.maxentities = numentities;
6207                 if (r_refdef.viewcache.entityvisible)
6208                         Mem_Free(r_refdef.viewcache.entityvisible);
6209                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6210         }
6211         if (r_refdef.viewcache.world_numclusters != numclusters)
6212         {
6213                 r_refdef.viewcache.world_numclusters = numclusters;
6214                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6215                 if (r_refdef.viewcache.world_pvsbits)
6216                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6217                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6218         }
6219         if (r_refdef.viewcache.world_numleafs != numleafs)
6220         {
6221                 r_refdef.viewcache.world_numleafs = numleafs;
6222                 if (r_refdef.viewcache.world_leafvisible)
6223                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6224                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6225         }
6226         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6227         {
6228                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6229                 if (r_refdef.viewcache.world_surfacevisible)
6230                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6231                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6232         }
6233 }
6234
6235 extern rtexture_t *loadingscreentexture;
6236 void gl_main_start(void)
6237 {
6238         loadingscreentexture = NULL;
6239         r_texture_blanknormalmap = NULL;
6240         r_texture_white = NULL;
6241         r_texture_grey128 = NULL;
6242         r_texture_black = NULL;
6243         r_texture_whitecube = NULL;
6244         r_texture_normalizationcube = NULL;
6245         r_texture_fogattenuation = NULL;
6246         r_texture_fogheighttexture = NULL;
6247         r_texture_gammaramps = NULL;
6248         r_texture_numcubemaps = 0;
6249
6250         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6251         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6252
6253         switch(vid.renderpath)
6254         {
6255         case RENDERPATH_GL20:
6256         case RENDERPATH_CGGL:
6257                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6258                 Cvar_SetValueQuick(&gl_combine, 1);
6259                 Cvar_SetValueQuick(&r_glsl, 1);
6260                 r_loadnormalmap = true;
6261                 r_loadgloss = true;
6262                 r_loadfog = false;
6263                 break;
6264         case RENDERPATH_GL13:
6265                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6266                 Cvar_SetValueQuick(&gl_combine, 1);
6267                 Cvar_SetValueQuick(&r_glsl, 0);
6268                 r_loadnormalmap = false;
6269                 r_loadgloss = false;
6270                 r_loadfog = true;
6271                 break;
6272         case RENDERPATH_GL11:
6273                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6274                 Cvar_SetValueQuick(&gl_combine, 0);
6275                 Cvar_SetValueQuick(&r_glsl, 0);
6276                 r_loadnormalmap = false;
6277                 r_loadgloss = false;
6278                 r_loadfog = true;
6279                 break;
6280         }
6281
6282         R_AnimCache_Free();
6283         R_FrameData_Reset();
6284
6285         r_numqueries = 0;
6286         r_maxqueries = 0;
6287         memset(r_queries, 0, sizeof(r_queries));
6288
6289         r_qwskincache = NULL;
6290         r_qwskincache_size = 0;
6291
6292         // set up r_skinframe loading system for textures
6293         memset(&r_skinframe, 0, sizeof(r_skinframe));
6294         r_skinframe.loadsequence = 1;
6295         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6296
6297         r_main_texturepool = R_AllocTexturePool();
6298         R_BuildBlankTextures();
6299         R_BuildNoTexture();
6300         if (vid.support.arb_texture_cube_map)
6301         {
6302                 R_BuildWhiteCube();
6303                 R_BuildNormalizationCube();
6304         }
6305         r_texture_fogattenuation = NULL;
6306         r_texture_fogheighttexture = NULL;
6307         r_texture_gammaramps = NULL;
6308         //r_texture_fogintensity = NULL;
6309         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6310         memset(&r_waterstate, 0, sizeof(r_waterstate));
6311         r_glsl_permutation = NULL;
6312         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6313         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6314         glslshaderstring = NULL;
6315 #ifdef SUPPORTCG
6316         r_cg_permutation = NULL;
6317         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6318         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
6319         cgshaderstring = NULL;
6320 #endif
6321         memset(&r_svbsp, 0, sizeof (r_svbsp));
6322
6323         r_refdef.fogmasktable_density = 0;
6324 }
6325
6326 void gl_main_shutdown(void)
6327 {
6328         R_AnimCache_Free();
6329         R_FrameData_Reset();
6330
6331         R_Main_FreeViewCache();
6332
6333         if (r_maxqueries)
6334                 qglDeleteQueriesARB(r_maxqueries, r_queries);
6335
6336         r_numqueries = 0;
6337         r_maxqueries = 0;
6338         memset(r_queries, 0, sizeof(r_queries));
6339
6340         r_qwskincache = NULL;
6341         r_qwskincache_size = 0;
6342
6343         // clear out the r_skinframe state
6344         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6345         memset(&r_skinframe, 0, sizeof(r_skinframe));
6346
6347         if (r_svbsp.nodes)
6348                 Mem_Free(r_svbsp.nodes);
6349         memset(&r_svbsp, 0, sizeof (r_svbsp));
6350         R_FreeTexturePool(&r_main_texturepool);
6351         loadingscreentexture = NULL;
6352         r_texture_blanknormalmap = NULL;
6353         r_texture_white = NULL;
6354         r_texture_grey128 = NULL;
6355         r_texture_black = NULL;
6356         r_texture_whitecube = NULL;
6357         r_texture_normalizationcube = NULL;
6358         r_texture_fogattenuation = NULL;
6359         r_texture_fogheighttexture = NULL;
6360         r_texture_gammaramps = NULL;
6361         r_texture_numcubemaps = 0;
6362         //r_texture_fogintensity = NULL;
6363         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6364         memset(&r_waterstate, 0, sizeof(r_waterstate));
6365         r_glsl_permutation = NULL;
6366         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6367         glslshaderstring = NULL;
6368 #ifdef SUPPORTCG
6369         r_cg_permutation = NULL;
6370         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6371         cgshaderstring = NULL;
6372 #endif
6373         R_GLSL_Restart_f();
6374 }
6375
6376 extern void CL_ParseEntityLump(char *entitystring);
6377 void gl_main_newmap(void)
6378 {
6379         // FIXME: move this code to client
6380         int l;
6381         char *entities, entname[MAX_QPATH];
6382         if (r_qwskincache)
6383                 Mem_Free(r_qwskincache);
6384         r_qwskincache = NULL;
6385         r_qwskincache_size = 0;
6386         if (cl.worldmodel)
6387         {
6388                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
6389                 l = (int)strlen(entname) - 4;
6390                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
6391                 {
6392                         memcpy(entname + l, ".ent", 5);
6393                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6394                         {
6395                                 CL_ParseEntityLump(entities);
6396                                 Mem_Free(entities);
6397                                 return;
6398                         }
6399                 }
6400                 if (cl.worldmodel->brush.entities)
6401                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
6402         }
6403         R_Main_FreeViewCache();
6404
6405         R_FrameData_Reset();
6406 }
6407
6408 void GL_Main_Init(void)
6409 {
6410         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6411
6412         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6413         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6414         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6415         if (gamemode == GAME_NEHAHRA)
6416         {
6417                 Cvar_RegisterVariable (&gl_fogenable);
6418                 Cvar_RegisterVariable (&gl_fogdensity);
6419                 Cvar_RegisterVariable (&gl_fogred);
6420                 Cvar_RegisterVariable (&gl_foggreen);
6421                 Cvar_RegisterVariable (&gl_fogblue);
6422                 Cvar_RegisterVariable (&gl_fogstart);
6423                 Cvar_RegisterVariable (&gl_fogend);
6424                 Cvar_RegisterVariable (&gl_skyclip);
6425         }
6426         Cvar_RegisterVariable(&r_motionblur);
6427         Cvar_RegisterVariable(&r_motionblur_maxblur);
6428         Cvar_RegisterVariable(&r_motionblur_bmin);
6429         Cvar_RegisterVariable(&r_motionblur_vmin);
6430         Cvar_RegisterVariable(&r_motionblur_vmax);
6431         Cvar_RegisterVariable(&r_motionblur_vcoeff);
6432         Cvar_RegisterVariable(&r_motionblur_randomize);
6433         Cvar_RegisterVariable(&r_damageblur);
6434         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6435         Cvar_RegisterVariable(&r_equalize_entities_minambient);
6436         Cvar_RegisterVariable(&r_equalize_entities_by);
6437         Cvar_RegisterVariable(&r_equalize_entities_to);
6438         Cvar_RegisterVariable(&r_depthfirst);
6439         Cvar_RegisterVariable(&r_useinfinitefarclip);
6440         Cvar_RegisterVariable(&r_farclip_base);
6441         Cvar_RegisterVariable(&r_farclip_world);
6442         Cvar_RegisterVariable(&r_nearclip);
6443         Cvar_RegisterVariable(&r_showbboxes);
6444         Cvar_RegisterVariable(&r_showsurfaces);
6445         Cvar_RegisterVariable(&r_showtris);
6446         Cvar_RegisterVariable(&r_shownormals);
6447         Cvar_RegisterVariable(&r_showlighting);
6448         Cvar_RegisterVariable(&r_showshadowvolumes);
6449         Cvar_RegisterVariable(&r_showcollisionbrushes);
6450         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6451         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6452         Cvar_RegisterVariable(&r_showdisabledepthtest);
6453         Cvar_RegisterVariable(&r_drawportals);
6454         Cvar_RegisterVariable(&r_drawentities);
6455         Cvar_RegisterVariable(&r_cullentities_trace);
6456         Cvar_RegisterVariable(&r_cullentities_trace_samples);
6457         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6458         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6459         Cvar_RegisterVariable(&r_cullentities_trace_delay);
6460         Cvar_RegisterVariable(&r_drawviewmodel);
6461         Cvar_RegisterVariable(&r_drawexteriormodel);
6462         Cvar_RegisterVariable(&r_speeds);
6463         Cvar_RegisterVariable(&r_fullbrights);
6464         Cvar_RegisterVariable(&r_wateralpha);
6465         Cvar_RegisterVariable(&r_dynamic);
6466         Cvar_RegisterVariable(&r_fullbright);
6467         Cvar_RegisterVariable(&r_shadows);
6468         Cvar_RegisterVariable(&r_shadows_darken);
6469         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6470         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6471         Cvar_RegisterVariable(&r_shadows_throwdistance);
6472         Cvar_RegisterVariable(&r_shadows_throwdirection);
6473         Cvar_RegisterVariable(&r_shadows_focus);
6474         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6475         Cvar_RegisterVariable(&r_q1bsp_skymasking);
6476         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6477         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6478         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6479         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6480         Cvar_RegisterVariable(&r_fog_exp2);
6481         Cvar_RegisterVariable(&r_drawfog);
6482         Cvar_RegisterVariable(&r_transparentdepthmasking);
6483         Cvar_RegisterVariable(&r_texture_dds_load);
6484         Cvar_RegisterVariable(&r_texture_dds_save);
6485         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6486         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6487         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6488         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6489         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6490         Cvar_RegisterVariable(&r_textureunits);
6491         Cvar_RegisterVariable(&gl_combine);
6492         Cvar_RegisterVariable(&r_glsl);
6493         Cvar_RegisterVariable(&r_glsl_deluxemapping);
6494         Cvar_RegisterVariable(&r_glsl_offsetmapping);
6495         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6496         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6497         Cvar_RegisterVariable(&r_glsl_postprocess);
6498         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6499         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6500         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6501         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6502         Cvar_RegisterVariable(&r_water);
6503         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6504         Cvar_RegisterVariable(&r_water_clippingplanebias);
6505         Cvar_RegisterVariable(&r_water_refractdistort);
6506         Cvar_RegisterVariable(&r_water_reflectdistort);
6507         Cvar_RegisterVariable(&r_lerpsprites);
6508         Cvar_RegisterVariable(&r_lerpmodels);
6509         Cvar_RegisterVariable(&r_lerplightstyles);
6510         Cvar_RegisterVariable(&r_waterscroll);
6511         Cvar_RegisterVariable(&r_bloom);
6512         Cvar_RegisterVariable(&r_bloom_colorscale);
6513         Cvar_RegisterVariable(&r_bloom_brighten);
6514         Cvar_RegisterVariable(&r_bloom_blur);
6515         Cvar_RegisterVariable(&r_bloom_resolution);
6516         Cvar_RegisterVariable(&r_bloom_colorexponent);
6517         Cvar_RegisterVariable(&r_bloom_colorsubtract);
6518         Cvar_RegisterVariable(&r_hdr);
6519         Cvar_RegisterVariable(&r_hdr_scenebrightness);
6520         Cvar_RegisterVariable(&r_hdr_glowintensity);
6521         Cvar_RegisterVariable(&r_hdr_range);
6522         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6523         Cvar_RegisterVariable(&developer_texturelogging);
6524         Cvar_RegisterVariable(&gl_lightmaps);
6525         Cvar_RegisterVariable(&r_test);
6526         Cvar_RegisterVariable(&r_batchmode);
6527         Cvar_RegisterVariable(&r_glsl_saturation);
6528         Cvar_RegisterVariable(&r_framedatasize);
6529         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6530                 Cvar_SetValue("r_fullbrights", 0);
6531         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
6532
6533         Cvar_RegisterVariable(&r_track_sprites);
6534         Cvar_RegisterVariable(&r_track_sprites_flags);
6535         Cvar_RegisterVariable(&r_track_sprites_scalew);
6536         Cvar_RegisterVariable(&r_track_sprites_scaleh);
6537         Cvar_RegisterVariable(&r_overheadsprites_perspective);
6538         Cvar_RegisterVariable(&r_overheadsprites_pushback);
6539 }
6540
6541 extern void R_Textures_Init(void);
6542 extern void GL_Draw_Init(void);
6543 extern void GL_Main_Init(void);
6544 extern void R_Shadow_Init(void);
6545 extern void R_Sky_Init(void);
6546 extern void GL_Surf_Init(void);
6547 extern void R_Particles_Init(void);
6548 extern void R_Explosion_Init(void);
6549 extern void gl_backend_init(void);
6550 extern void Sbar_Init(void);
6551 extern void R_LightningBeams_Init(void);
6552 extern void Mod_RenderInit(void);
6553 extern void Font_Init(void);
6554
6555 void Render_Init(void)
6556 {
6557         gl_backend_init();
6558         R_Textures_Init();
6559         GL_Main_Init();
6560         Font_Init();
6561         GL_Draw_Init();
6562         R_Shadow_Init();
6563         R_Sky_Init();
6564         GL_Surf_Init();
6565         Sbar_Init();
6566         R_Particles_Init();
6567         R_Explosion_Init();
6568         R_LightningBeams_Init();
6569         Mod_RenderInit();
6570 }
6571
6572 /*
6573 ===============
6574 GL_Init
6575 ===============
6576 */
6577 extern char *ENGINE_EXTENSIONS;
6578 void GL_Init (void)
6579 {
6580         gl_renderer = (const char *)qglGetString(GL_RENDERER);
6581         gl_vendor = (const char *)qglGetString(GL_VENDOR);
6582         gl_version = (const char *)qglGetString(GL_VERSION);
6583         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6584
6585         if (!gl_extensions)
6586                 gl_extensions = "";
6587         if (!gl_platformextensions)
6588                 gl_platformextensions = "";
6589
6590         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6591         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6592         Con_Printf("GL_VERSION: %s\n", gl_version);
6593         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6594         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6595
6596         VID_CheckExtensions();
6597
6598         // LordHavoc: report supported extensions
6599         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6600
6601         // clear to black (loading plaque will be seen over this)
6602         CHECKGLERROR
6603         qglClearColor(0,0,0,1);CHECKGLERROR
6604         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6605 }
6606
6607 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6608 {
6609         int i;
6610         mplane_t *p;
6611         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6612         {
6613                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6614                 if (i == 4)
6615                         continue;
6616                 p = r_refdef.view.frustum + i;
6617                 switch(p->signbits)
6618                 {
6619                 default:
6620                 case 0:
6621                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6622                                 return true;
6623                         break;
6624                 case 1:
6625                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6626                                 return true;
6627                         break;
6628                 case 2:
6629                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6630                                 return true;
6631                         break;
6632                 case 3:
6633                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6634                                 return true;
6635                         break;
6636                 case 4:
6637                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6638                                 return true;
6639                         break;
6640                 case 5:
6641                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6642                                 return true;
6643                         break;
6644                 case 6:
6645                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6646                                 return true;
6647                         break;
6648                 case 7:
6649                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6650                                 return true;
6651                         break;
6652                 }
6653         }
6654         return false;
6655 }
6656
6657 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6658 {
6659         int i;
6660         const mplane_t *p;
6661         for (i = 0;i < numplanes;i++)
6662         {
6663                 p = planes + i;
6664                 switch(p->signbits)
6665                 {
6666                 default:
6667                 case 0:
6668                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6669                                 return true;
6670                         break;
6671                 case 1:
6672                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6673                                 return true;
6674                         break;
6675                 case 2:
6676                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6677                                 return true;
6678                         break;
6679                 case 3:
6680                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6681                                 return true;
6682                         break;
6683                 case 4:
6684                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6685                                 return true;
6686                         break;
6687                 case 5:
6688                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6689                                 return true;
6690                         break;
6691                 case 6:
6692                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6693                                 return true;
6694                         break;
6695                 case 7:
6696                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6697                                 return true;
6698                         break;
6699                 }
6700         }
6701         return false;
6702 }
6703
6704 //==================================================================================
6705
6706 // LordHavoc: this stores temporary data used within the same frame
6707
6708 qboolean r_framedata_failed;
6709 static size_t r_framedata_size;
6710 static size_t r_framedata_current;
6711 static void *r_framedata_base;
6712
6713 void R_FrameData_Reset(void)
6714 {
6715         if (r_framedata_base)
6716                 Mem_Free(r_framedata_base);
6717         r_framedata_base = NULL;
6718         r_framedata_size = 0;
6719         r_framedata_current = 0;
6720         r_framedata_failed = false;
6721 }
6722
6723 void R_FrameData_NewFrame(void)
6724 {
6725         size_t wantedsize;
6726         if (r_framedata_failed)
6727                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6728         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6729         wantedsize = bound(65536, wantedsize, 128*1024*1024);
6730         if (r_framedata_size != wantedsize)
6731         {
6732                 r_framedata_size = wantedsize;
6733                 if (r_framedata_base)
6734                         Mem_Free(r_framedata_base);
6735                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6736         }
6737         r_framedata_current = 0;
6738         r_framedata_failed = false;
6739 }
6740
6741 void *R_FrameData_Alloc(size_t size)
6742 {
6743         void *data;
6744
6745         // align to 16 byte boundary
6746         size = (size + 15) & ~15;
6747         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6748         r_framedata_current += size;
6749
6750         // check overflow
6751         if (r_framedata_current > r_framedata_size)
6752                 r_framedata_failed = true;
6753
6754         // return NULL on everything after a failure
6755         if (r_framedata_failed)
6756                 return NULL;
6757
6758         return data;
6759 }
6760
6761 void *R_FrameData_Store(size_t size, void *data)
6762 {
6763         void *d = R_FrameData_Alloc(size);
6764         if (d)
6765                 memcpy(d, data, size);
6766         return d;
6767 }
6768
6769 //==================================================================================
6770
6771 // LordHavoc: animcache originally written by Echon, rewritten since then
6772
6773 /**
6774  * Animation cache prevents re-generating mesh data for an animated model
6775  * multiple times in one frame for lighting, shadowing, reflections, etc.
6776  */
6777
6778 void R_AnimCache_Free(void)
6779 {
6780 }
6781
6782 void R_AnimCache_ClearCache(void)
6783 {
6784         int i;
6785         entity_render_t *ent;
6786
6787         for (i = 0;i < r_refdef.scene.numentities;i++)
6788         {
6789                 ent = r_refdef.scene.entities[i];
6790                 ent->animcache_vertex3f = NULL;
6791                 ent->animcache_normal3f = NULL;
6792                 ent->animcache_svector3f = NULL;
6793                 ent->animcache_tvector3f = NULL;
6794         }
6795 }
6796
6797 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6798 {
6799         dp_model_t *model = ent->model;
6800         int numvertices;
6801         // see if it's already cached this frame
6802         if (ent->animcache_vertex3f)
6803         {
6804                 // add normals/tangents if needed
6805                 if (wantnormals || wanttangents)
6806                 {
6807                         if (ent->animcache_normal3f)
6808                                 wantnormals = false;
6809                         if (ent->animcache_svector3f)
6810                                 wanttangents = false;
6811                         if (wantnormals || wanttangents)
6812                         {
6813                                 numvertices = model->surfmesh.num_vertices;
6814                                 if (wantnormals)
6815                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6816                                 if (wanttangents)
6817                                 {
6818                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6819                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6820                                 }
6821                                 if (!r_framedata_failed)
6822                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6823                         }
6824                 }
6825         }
6826         else
6827         {
6828                 // see if this ent is worth caching
6829                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6830                         return false;
6831                 // get some memory for this entity and generate mesh data
6832                 numvertices = model->surfmesh.num_vertices;
6833                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6834                 if (wantnormals)
6835                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6836                 if (wanttangents)
6837                 {
6838                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6839                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6840                 }
6841                 if (!r_framedata_failed)
6842                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6843         }
6844         return !r_framedata_failed;
6845 }
6846
6847 void R_AnimCache_CacheVisibleEntities(void)
6848 {
6849         int i;
6850         qboolean wantnormals = !r_showsurfaces.integer;
6851         qboolean wanttangents = !r_showsurfaces.integer;
6852
6853         switch(vid.renderpath)
6854         {
6855         case RENDERPATH_GL20:
6856         case RENDERPATH_CGGL:
6857                 break;
6858         case RENDERPATH_GL13:
6859         case RENDERPATH_GL11:
6860                 wanttangents = false;
6861                 break;
6862         }
6863
6864         // TODO: thread this
6865         // NOTE: R_PrepareRTLights() also caches entities
6866
6867         for (i = 0;i < r_refdef.scene.numentities;i++)
6868                 if (r_refdef.viewcache.entityvisible[i])
6869                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6870 }
6871
6872 //==================================================================================
6873
6874 static void R_View_UpdateEntityLighting (void)
6875 {
6876         int i;
6877         entity_render_t *ent;
6878         vec3_t tempdiffusenormal, avg;
6879         vec_t f, fa, fd, fdd;
6880         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
6881
6882         for (i = 0;i < r_refdef.scene.numentities;i++)
6883         {
6884                 ent = r_refdef.scene.entities[i];
6885
6886                 // skip unseen models
6887                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
6888                         continue;
6889
6890                 // skip bsp models
6891                 if (ent->model && ent->model->brush.num_leafs)
6892                 {
6893                         // TODO: use modellight for r_ambient settings on world?
6894                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6895                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6896                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6897                         continue;
6898                 }
6899
6900                 // fetch the lighting from the worldmodel data
6901                 VectorClear(ent->modellight_ambient);
6902                 VectorClear(ent->modellight_diffuse);
6903                 VectorClear(tempdiffusenormal);
6904                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6905                 {
6906                         vec3_t org;
6907                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6908                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6909                         if(ent->flags & RENDER_EQUALIZE)
6910                         {
6911                                 // first fix up ambient lighting...
6912                                 if(r_equalize_entities_minambient.value > 0)
6913                                 {
6914                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6915                                         if(fd > 0)
6916                                         {
6917                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6918                                                 if(fa < r_equalize_entities_minambient.value * fd)
6919                                                 {
6920                                                         // solve:
6921                                                         //   fa'/fd' = minambient
6922                                                         //   fa'+0.25*fd' = fa+0.25*fd
6923                                                         //   ...
6924                                                         //   fa' = fd' * minambient
6925                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6926                                                         //   ...
6927                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6928                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6929                                                         //   ...
6930                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6931                                                         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
6932                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6933                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6934                                                 }
6935                                         }
6936                                 }
6937
6938                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6939                                 {
6940                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6941                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6942                                         if(f > 0)
6943                                         {
6944                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6945                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6946                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6947                                         }
6948                                 }
6949                         }
6950                 }
6951                 else // highly rare
6952                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6953
6954                 // move the light direction into modelspace coordinates for lighting code
6955                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6956                 if(VectorLength2(ent->modellight_lightdir) == 0)
6957                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6958                 VectorNormalize(ent->modellight_lightdir);
6959         }
6960 }
6961
6962 #define MAX_LINEOFSIGHTTRACES 64
6963
6964 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6965 {
6966         int i;
6967         vec3_t boxmins, boxmaxs;
6968         vec3_t start;
6969         vec3_t end;
6970         dp_model_t *model = r_refdef.scene.worldmodel;
6971
6972         if (!model || !model->brush.TraceLineOfSight)
6973                 return true;
6974
6975         // expand the box a little
6976         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6977         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6978         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6979         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6980         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6981         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6982
6983         // return true if eye is inside enlarged box
6984         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
6985                 return true;
6986
6987         // try center
6988         VectorCopy(eye, start);
6989         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6990         if (model->brush.TraceLineOfSight(model, start, end))
6991                 return true;
6992
6993         // try various random positions
6994         for (i = 0;i < numsamples;i++)
6995         {
6996                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6997                 if (model->brush.TraceLineOfSight(model, start, end))
6998                         return true;
6999         }
7000
7001         return false;
7002 }
7003
7004
7005 static void R_View_UpdateEntityVisible (void)
7006 {
7007         int i;
7008         int renderimask;
7009         int samples;
7010         entity_render_t *ent;
7011
7012         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7013                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7014                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
7015                 :                                                          RENDER_EXTERIORMODEL;
7016         if (!r_drawviewmodel.integer)
7017                 renderimask |= RENDER_VIEWMODEL;
7018         if (!r_drawexteriormodel.integer)
7019                 renderimask |= RENDER_EXTERIORMODEL;
7020         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7021         {
7022                 // worldmodel can check visibility
7023                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7024                 for (i = 0;i < r_refdef.scene.numentities;i++)
7025                 {
7026                         ent = r_refdef.scene.entities[i];
7027                         if (!(ent->flags & renderimask))
7028                         if (!R_CullBox(ent->mins, ent->maxs) || (ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
7029                         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))
7030                                 r_refdef.viewcache.entityvisible[i] = true;
7031                 }
7032                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7033                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7034                 {
7035                         for (i = 0;i < r_refdef.scene.numentities;i++)
7036                         {
7037                                 ent = r_refdef.scene.entities[i];
7038                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7039                                 {
7040                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7041                                         if (samples < 0)
7042                                                 continue; // temp entities do pvs only
7043                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7044                                                 ent->last_trace_visibility = realtime;
7045                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7046                                                 r_refdef.viewcache.entityvisible[i] = 0;
7047                                 }
7048                         }
7049                 }
7050         }
7051         else
7052         {
7053                 // no worldmodel or it can't check visibility
7054                 for (i = 0;i < r_refdef.scene.numentities;i++)
7055                 {
7056                         ent = r_refdef.scene.entities[i];
7057                         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));
7058                 }
7059         }
7060 }
7061
7062 /// only used if skyrendermasked, and normally returns false
7063 int R_DrawBrushModelsSky (void)
7064 {
7065         int i, sky;
7066         entity_render_t *ent;
7067
7068         sky = false;
7069         for (i = 0;i < r_refdef.scene.numentities;i++)
7070         {
7071                 if (!r_refdef.viewcache.entityvisible[i])
7072                         continue;
7073                 ent = r_refdef.scene.entities[i];
7074                 if (!ent->model || !ent->model->DrawSky)
7075                         continue;
7076                 ent->model->DrawSky(ent);
7077                 sky = true;
7078         }
7079         return sky;
7080 }
7081
7082 static void R_DrawNoModel(entity_render_t *ent);
7083 static void R_DrawModels(void)
7084 {
7085         int i;
7086         entity_render_t *ent;
7087
7088         for (i = 0;i < r_refdef.scene.numentities;i++)
7089         {
7090                 if (!r_refdef.viewcache.entityvisible[i])
7091                         continue;
7092                 ent = r_refdef.scene.entities[i];
7093                 r_refdef.stats.entities++;
7094                 if (ent->model && ent->model->Draw != NULL)
7095                         ent->model->Draw(ent);
7096                 else
7097                         R_DrawNoModel(ent);
7098         }
7099 }
7100
7101 static void R_DrawModelsDepth(void)
7102 {
7103         int i;
7104         entity_render_t *ent;
7105
7106         for (i = 0;i < r_refdef.scene.numentities;i++)
7107         {
7108                 if (!r_refdef.viewcache.entityvisible[i])
7109                         continue;
7110                 ent = r_refdef.scene.entities[i];
7111                 if (ent->model && ent->model->DrawDepth != NULL)
7112                         ent->model->DrawDepth(ent);
7113         }
7114 }
7115
7116 static void R_DrawModelsDebug(void)
7117 {
7118         int i;
7119         entity_render_t *ent;
7120
7121         for (i = 0;i < r_refdef.scene.numentities;i++)
7122         {
7123                 if (!r_refdef.viewcache.entityvisible[i])
7124                         continue;
7125                 ent = r_refdef.scene.entities[i];
7126                 if (ent->model && ent->model->DrawDebug != NULL)
7127                         ent->model->DrawDebug(ent);
7128         }
7129 }
7130
7131 static void R_DrawModelsAddWaterPlanes(void)
7132 {
7133         int i;
7134         entity_render_t *ent;
7135
7136         for (i = 0;i < r_refdef.scene.numentities;i++)
7137         {
7138                 if (!r_refdef.viewcache.entityvisible[i])
7139                         continue;
7140                 ent = r_refdef.scene.entities[i];
7141                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7142                         ent->model->DrawAddWaterPlanes(ent);
7143         }
7144 }
7145
7146 static void R_View_SetFrustum(void)
7147 {
7148         int i;
7149         double slopex, slopey;
7150         vec3_t forward, left, up, origin;
7151
7152         // we can't trust r_refdef.view.forward and friends in reflected scenes
7153         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7154
7155 #if 0
7156         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7157         r_refdef.view.frustum[0].normal[1] = 0 - 0;
7158         r_refdef.view.frustum[0].normal[2] = -1 - 0;
7159         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7160         r_refdef.view.frustum[1].normal[1] = 0 + 0;
7161         r_refdef.view.frustum[1].normal[2] = -1 + 0;
7162         r_refdef.view.frustum[2].normal[0] = 0 - 0;
7163         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7164         r_refdef.view.frustum[2].normal[2] = -1 - 0;
7165         r_refdef.view.frustum[3].normal[0] = 0 + 0;
7166         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7167         r_refdef.view.frustum[3].normal[2] = -1 + 0;
7168 #endif
7169
7170 #if 0
7171         zNear = r_refdef.nearclip;
7172         nudge = 1.0 - 1.0 / (1<<23);
7173         r_refdef.view.frustum[4].normal[0] = 0 - 0;
7174         r_refdef.view.frustum[4].normal[1] = 0 - 0;
7175         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7176         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7177         r_refdef.view.frustum[5].normal[0] = 0 + 0;
7178         r_refdef.view.frustum[5].normal[1] = 0 + 0;
7179         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7180         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7181 #endif
7182
7183
7184
7185 #if 0
7186         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7187         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7188         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7189         r_refdef.view.frustum[0].dist = m[15] - m[12];
7190
7191         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7192         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7193         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7194         r_refdef.view.frustum[1].dist = m[15] + m[12];
7195
7196         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7197         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7198         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7199         r_refdef.view.frustum[2].dist = m[15] - m[13];
7200
7201         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7202         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7203         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7204         r_refdef.view.frustum[3].dist = m[15] + m[13];
7205
7206         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7207         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7208         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7209         r_refdef.view.frustum[4].dist = m[15] - m[14];
7210
7211         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7212         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7213         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7214         r_refdef.view.frustum[5].dist = m[15] + m[14];
7215 #endif
7216
7217         if (r_refdef.view.useperspective)
7218         {
7219                 slopex = 1.0 / r_refdef.view.frustum_x;
7220                 slopey = 1.0 / r_refdef.view.frustum_y;
7221                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
7222                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
7223                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
7224                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
7225                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7226
7227                 // Leaving those out was a mistake, those were in the old code, and they
7228                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7229                 // I couldn't reproduce it after adding those normalizations. --blub
7230                 VectorNormalize(r_refdef.view.frustum[0].normal);
7231                 VectorNormalize(r_refdef.view.frustum[1].normal);
7232                 VectorNormalize(r_refdef.view.frustum[2].normal);
7233                 VectorNormalize(r_refdef.view.frustum[3].normal);
7234
7235                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7236                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
7237                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
7238                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left,  1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
7239                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * r_refdef.view.frustum_x, left,  1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
7240
7241                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7242                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7243                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7244                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7245                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7246         }
7247         else
7248         {
7249                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7250                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7251                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7252                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7253                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7254                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7255                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7256                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7257                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7258                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7259         }
7260         r_refdef.view.numfrustumplanes = 5;
7261
7262         if (r_refdef.view.useclipplane)
7263         {
7264                 r_refdef.view.numfrustumplanes = 6;
7265                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7266         }
7267
7268         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7269                 PlaneClassify(r_refdef.view.frustum + i);
7270
7271         // LordHavoc: note to all quake engine coders, Quake had a special case
7272         // for 90 degrees which assumed a square view (wrong), so I removed it,
7273         // Quake2 has it disabled as well.
7274
7275         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7276         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7277         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7278         //PlaneClassify(&frustum[0]);
7279
7280         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7281         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7282         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7283         //PlaneClassify(&frustum[1]);
7284
7285         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7286         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7287         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7288         //PlaneClassify(&frustum[2]);
7289
7290         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7291         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7292         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7293         //PlaneClassify(&frustum[3]);
7294
7295         // nearclip plane
7296         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7297         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7298         //PlaneClassify(&frustum[4]);
7299 }
7300
7301 void R_View_Update(void)
7302 {
7303         R_Main_ResizeViewCache();
7304         R_View_SetFrustum();
7305         R_View_WorldVisibility(r_refdef.view.useclipplane);
7306         R_View_UpdateEntityVisible();
7307         R_View_UpdateEntityLighting();
7308 }
7309
7310 void R_SetupView(qboolean allowwaterclippingplane)
7311 {
7312         const float *customclipplane = NULL;
7313         float plane[4];
7314         if (r_refdef.view.useclipplane && allowwaterclippingplane)
7315         {
7316                 // LordHavoc: couldn't figure out how to make this approach the
7317                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7318                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7319                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7320                         dist = r_refdef.view.clipplane.dist;
7321                 plane[0] = r_refdef.view.clipplane.normal[0];
7322                 plane[1] = r_refdef.view.clipplane.normal[1];
7323                 plane[2] = r_refdef.view.clipplane.normal[2];
7324                 plane[3] = dist;
7325                 customclipplane = plane;
7326         }
7327
7328         if (!r_refdef.view.useperspective)
7329                 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);
7330         else if (vid.stencil && r_useinfinitefarclip.integer)
7331                 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);
7332         else
7333                 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);
7334         R_SetViewport(&r_refdef.view.viewport);
7335 }
7336
7337 void R_EntityMatrix(const matrix4x4_t *matrix)
7338 {
7339         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7340         {
7341                 gl_modelmatrixchanged = false;
7342                 gl_modelmatrix = *matrix;
7343                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7344                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7345                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7346                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7347                 CHECKGLERROR
7348                 switch(vid.renderpath)
7349                 {
7350                 case RENDERPATH_GL20:
7351                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7352                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7353                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7354                         break;
7355                 case RENDERPATH_CGGL:
7356 #ifdef SUPPORTCG
7357                         CHECKCGERROR
7358                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
7359                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
7360                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7361 #endif
7362                         break;
7363                 case RENDERPATH_GL13:
7364                 case RENDERPATH_GL11:
7365                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7366                         break;
7367                 }
7368         }
7369 }
7370
7371 void R_ResetViewRendering2D(void)
7372 {
7373         r_viewport_t viewport;
7374         DrawQ_Finish();
7375
7376         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7377         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);
7378         R_SetViewport(&viewport);
7379         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7380         GL_Color(1, 1, 1, 1);
7381         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7382         GL_BlendFunc(GL_ONE, GL_ZERO);
7383         GL_AlphaTest(false);
7384         GL_ScissorTest(false);
7385         GL_DepthMask(false);
7386         GL_DepthRange(0, 1);
7387         GL_DepthTest(false);
7388         R_EntityMatrix(&identitymatrix);
7389         R_Mesh_ResetTextureState();
7390         GL_PolygonOffset(0, 0);
7391         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7392         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7393         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7394         qglStencilMask(~0);CHECKGLERROR
7395         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7396         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7397         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
7398 }
7399
7400 void R_ResetViewRendering3D(void)
7401 {
7402         DrawQ_Finish();
7403
7404         R_SetupView(true);
7405         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7406         GL_Color(1, 1, 1, 1);
7407         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7408         GL_BlendFunc(GL_ONE, GL_ZERO);
7409         GL_AlphaTest(false);
7410         GL_ScissorTest(true);
7411         GL_DepthMask(true);
7412         GL_DepthRange(0, 1);
7413         GL_DepthTest(true);
7414         R_EntityMatrix(&identitymatrix);
7415         R_Mesh_ResetTextureState();
7416         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7417         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7418         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7419         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7420         qglStencilMask(~0);CHECKGLERROR
7421         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7422         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7423         GL_CullFace(r_refdef.view.cullface_back);
7424 }
7425
7426 /*
7427 ================
7428 R_RenderView_UpdateViewVectors
7429 ================
7430 */
7431 static void R_RenderView_UpdateViewVectors(void)
7432 {
7433         // break apart the view matrix into vectors for various purposes
7434         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7435         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7436         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7437         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7438         // make an inverted copy of the view matrix for tracking sprites
7439         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7440 }
7441
7442 void R_RenderScene(void);
7443 void R_RenderWaterPlanes(void);
7444
7445 static void R_Water_StartFrame(void)
7446 {
7447         int i;
7448         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
7449         r_waterstate_waterplane_t *p;
7450
7451         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
7452                 return;
7453
7454         switch(vid.renderpath)
7455         {
7456         case RENDERPATH_GL20:
7457         case RENDERPATH_CGGL:
7458                 break;
7459         case RENDERPATH_GL13:
7460         case RENDERPATH_GL11:
7461                 return;
7462         }
7463
7464         // set waterwidth and waterheight to the water resolution that will be
7465         // used (often less than the screen resolution for faster rendering)
7466         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
7467         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
7468
7469         // calculate desired texture sizes
7470         // can't use water if the card does not support the texture size
7471         if (!r_water.integer || r_showsurfaces.integer)
7472                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
7473         else if (vid.support.arb_texture_non_power_of_two)
7474         {
7475                 texturewidth = waterwidth;
7476                 textureheight = waterheight;
7477                 camerawidth = waterwidth;
7478                 cameraheight = waterheight;
7479         }
7480         else
7481         {
7482                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
7483                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
7484                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
7485                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
7486         }
7487
7488         // allocate textures as needed
7489         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
7490         {
7491                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7492                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
7493                 {
7494                         if (p->texture_refraction)
7495                                 R_FreeTexture(p->texture_refraction);
7496                         p->texture_refraction = NULL;
7497                         if (p->texture_reflection)
7498                                 R_FreeTexture(p->texture_reflection);
7499                         p->texture_reflection = NULL;
7500                         if (p->texture_camera)
7501                                 R_FreeTexture(p->texture_camera);
7502                         p->texture_camera = NULL;
7503                 }
7504                 memset(&r_waterstate, 0, sizeof(r_waterstate));
7505                 r_waterstate.texturewidth = texturewidth;
7506                 r_waterstate.textureheight = textureheight;
7507                 r_waterstate.camerawidth = camerawidth;
7508                 r_waterstate.cameraheight = cameraheight;
7509         }
7510
7511         if (r_waterstate.texturewidth)
7512         {
7513                 r_waterstate.enabled = true;
7514
7515                 // when doing a reduced render (HDR) we want to use a smaller area
7516                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
7517                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
7518
7519                 // set up variables that will be used in shader setup
7520                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7521                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7522                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7523                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7524         }
7525
7526         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7527         r_waterstate.numwaterplanes = 0;
7528 }
7529
7530 void R_Water_AddWaterPlane(msurface_t *surface)
7531 {
7532         int triangleindex, planeindex;
7533         const int *e;
7534         vec3_t vert[3];
7535         vec3_t normal;
7536         vec3_t center;
7537         mplane_t plane;
7538         int cam_ent;
7539         r_waterstate_waterplane_t *p;
7540         texture_t *t = R_GetCurrentTexture(surface->texture);
7541         cam_ent = t->camera_entity;
7542         if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
7543                 cam_ent = 0;
7544
7545         // just use the first triangle with a valid normal for any decisions
7546         VectorClear(normal);
7547         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
7548         {
7549                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
7550                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
7551                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
7552                 TriangleNormal(vert[0], vert[1], vert[2], normal);
7553                 if (VectorLength2(normal) >= 0.001)
7554                         break;
7555         }
7556
7557         VectorCopy(normal, plane.normal);
7558         VectorNormalize(plane.normal);
7559         plane.dist = DotProduct(vert[0], plane.normal);
7560         PlaneClassify(&plane);
7561         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
7562         {
7563                 // skip backfaces (except if nocullface is set)
7564                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
7565                         return;
7566                 VectorNegate(plane.normal, plane.normal);
7567                 plane.dist *= -1;
7568                 PlaneClassify(&plane);
7569         }
7570
7571
7572         // find a matching plane if there is one
7573         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7574                 if(p->camera_entity == t->camera_entity)
7575                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
7576                                 break;
7577         if (planeindex >= r_waterstate.maxwaterplanes)
7578                 return; // nothing we can do, out of planes
7579
7580         // if this triangle does not fit any known plane rendered this frame, add one
7581         if (planeindex >= r_waterstate.numwaterplanes)
7582         {
7583                 // store the new plane
7584                 r_waterstate.numwaterplanes++;
7585                 p->plane = plane;
7586                 // clear materialflags and pvs
7587                 p->materialflags = 0;
7588                 p->pvsvalid = false;
7589                 p->camera_entity = t->camera_entity;
7590         }
7591         // merge this surface's materialflags into the waterplane
7592         p->materialflags |= t->currentmaterialflags;
7593         if(!(p->materialflags & MATERIALFLAG_CAMERA))
7594         {
7595                 // merge this surface's PVS into the waterplane
7596                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7597                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7598                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7599                 {
7600                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7601                         p->pvsvalid = true;
7602                 }
7603         }
7604 }
7605
7606 static void R_Water_ProcessPlanes(void)
7607 {
7608         r_refdef_view_t originalview;
7609         r_refdef_view_t myview;
7610         int planeindex;
7611         r_waterstate_waterplane_t *p;
7612         vec3_t visorigin;
7613
7614         originalview = r_refdef.view;
7615
7616         // make sure enough textures are allocated
7617         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7618         {
7619                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7620                 {
7621                         if (!p->texture_refraction)
7622                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7623                         if (!p->texture_refraction)
7624                                 goto error;
7625                 }
7626                 else if (p->materialflags & MATERIALFLAG_CAMERA)
7627                 {
7628                         if (!p->texture_camera)
7629                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR, NULL);
7630                         if (!p->texture_camera)
7631                                 goto error;
7632                 }
7633
7634                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7635                 {
7636                         if (!p->texture_reflection)
7637                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7638                         if (!p->texture_reflection)
7639                                 goto error;
7640                 }
7641         }
7642
7643         // render views
7644         r_refdef.view = originalview;
7645         r_refdef.view.showdebug = false;
7646         r_refdef.view.width = r_waterstate.waterwidth;
7647         r_refdef.view.height = r_waterstate.waterheight;
7648         r_refdef.view.useclipplane = true;
7649         myview = r_refdef.view;
7650         r_waterstate.renderingscene = true;
7651         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7652         {
7653                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7654                 {
7655                         r_refdef.view = myview;
7656                         // render reflected scene and copy into texture
7657                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7658                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7659                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7660                         r_refdef.view.clipplane = p->plane;
7661                         // reverse the cullface settings for this render
7662                         r_refdef.view.cullface_front = GL_FRONT;
7663                         r_refdef.view.cullface_back = GL_BACK;
7664                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7665                         {
7666                                 r_refdef.view.usecustompvs = true;
7667                                 if (p->pvsvalid)
7668                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7669                                 else
7670                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7671                         }
7672
7673                         R_ResetViewRendering3D();
7674                         R_ClearScreen(r_refdef.fogenabled);
7675                         R_View_Update();
7676                         R_RenderScene();
7677
7678                         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);
7679                 }
7680
7681                 // render the normal view scene and copy into texture
7682                 // (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)
7683                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7684                 {
7685                         r_waterstate.renderingrefraction = true;
7686                         r_refdef.view = myview;
7687
7688                         r_refdef.view.clipplane = p->plane;
7689                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7690                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7691
7692                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
7693                         {
7694                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
7695                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
7696                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
7697                                 R_RenderView_UpdateViewVectors();
7698                                 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);
7699                         }
7700
7701                         PlaneClassify(&r_refdef.view.clipplane);
7702
7703                         R_ResetViewRendering3D();
7704                         R_ClearScreen(r_refdef.fogenabled);
7705                         R_View_Update();
7706                         R_RenderScene();
7707
7708                         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);
7709                         r_waterstate.renderingrefraction = false;
7710                 }
7711                 else if (p->materialflags & MATERIALFLAG_CAMERA)
7712                 {
7713                         r_refdef.view = myview;
7714
7715                         r_refdef.view.clipplane = p->plane;
7716                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7717                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7718
7719                         r_refdef.view.width = r_waterstate.camerawidth;
7720                         r_refdef.view.height = r_waterstate.cameraheight;
7721                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
7722                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
7723
7724                         if(p->camera_entity)
7725                         {
7726                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
7727                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
7728                         }
7729
7730                         // reverse the cullface settings for this render
7731                         r_refdef.view.cullface_front = GL_FRONT;
7732                         r_refdef.view.cullface_back = GL_BACK;
7733                         // also reverse the view matrix
7734                         Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, -1, 1);
7735                         R_RenderView_UpdateViewVectors();
7736                         if(p->camera_entity)
7737                                 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);
7738                         
7739                         // camera needs no clipplane
7740                         r_refdef.view.useclipplane = false;
7741
7742                         PlaneClassify(&r_refdef.view.clipplane);
7743
7744                         R_ResetViewRendering3D();
7745                         R_ClearScreen(r_refdef.fogenabled);
7746                         R_View_Update();
7747                         R_RenderScene();
7748
7749                         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);
7750                         r_waterstate.renderingrefraction = false;
7751                 }
7752
7753         }
7754         r_waterstate.renderingscene = false;
7755         r_refdef.view = originalview;
7756         R_ResetViewRendering3D();
7757         R_ClearScreen(r_refdef.fogenabled);
7758         R_View_Update();
7759         return;
7760 error:
7761         r_refdef.view = originalview;
7762         r_waterstate.renderingscene = false;
7763         Cvar_SetValueQuick(&r_water, 0);
7764         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
7765         return;
7766 }
7767
7768 void R_Bloom_StartFrame(void)
7769 {
7770         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7771
7772         switch(vid.renderpath)
7773         {
7774         case RENDERPATH_GL20:
7775         case RENDERPATH_CGGL:
7776                 break;
7777         case RENDERPATH_GL13:
7778         case RENDERPATH_GL11:
7779                 return;
7780         }
7781
7782         // set bloomwidth and bloomheight to the bloom resolution that will be
7783         // used (often less than the screen resolution for faster rendering)
7784         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7785         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7786         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7787         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7788         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7789
7790         // calculate desired texture sizes
7791         if (vid.support.arb_texture_non_power_of_two)
7792         {
7793                 screentexturewidth = r_refdef.view.width;
7794                 screentextureheight = r_refdef.view.height;
7795                 bloomtexturewidth = r_bloomstate.bloomwidth;
7796                 bloomtextureheight = r_bloomstate.bloomheight;
7797         }
7798         else
7799         {
7800                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
7801                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
7802                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
7803                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
7804         }
7805
7806         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))
7807         {
7808                 Cvar_SetValueQuick(&r_hdr, 0);
7809                 Cvar_SetValueQuick(&r_bloom, 0);
7810                 Cvar_SetValueQuick(&r_motionblur, 0);
7811                 Cvar_SetValueQuick(&r_damageblur, 0);
7812         }
7813
7814         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)))
7815                 screentexturewidth = screentextureheight = 0;
7816         if (!r_hdr.integer && !r_bloom.integer)
7817                 bloomtexturewidth = bloomtextureheight = 0;
7818
7819         // allocate textures as needed
7820         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7821         {
7822                 if (r_bloomstate.texture_screen)
7823                         R_FreeTexture(r_bloomstate.texture_screen);
7824                 r_bloomstate.texture_screen = NULL;
7825                 r_bloomstate.screentexturewidth = screentexturewidth;
7826                 r_bloomstate.screentextureheight = screentextureheight;
7827                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7828                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7829         }
7830         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7831         {
7832                 if (r_bloomstate.texture_bloom)
7833                         R_FreeTexture(r_bloomstate.texture_bloom);
7834                 r_bloomstate.texture_bloom = NULL;
7835                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7836                 r_bloomstate.bloomtextureheight = bloomtextureheight;
7837                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7838                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7839         }
7840
7841         // when doing a reduced render (HDR) we want to use a smaller area
7842         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7843         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7844         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7845         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7846         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7847
7848         // set up a texcoord array for the full resolution screen image
7849         // (we have to keep this around to copy back during final render)
7850         r_bloomstate.screentexcoord2f[0] = 0;
7851         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7852         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7853         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7854         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7855         r_bloomstate.screentexcoord2f[5] = 0;
7856         r_bloomstate.screentexcoord2f[6] = 0;
7857         r_bloomstate.screentexcoord2f[7] = 0;
7858
7859         // set up a texcoord array for the reduced resolution bloom image
7860         // (which will be additive blended over the screen image)
7861         r_bloomstate.bloomtexcoord2f[0] = 0;
7862         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7863         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7864         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7865         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7866         r_bloomstate.bloomtexcoord2f[5] = 0;
7867         r_bloomstate.bloomtexcoord2f[6] = 0;
7868         r_bloomstate.bloomtexcoord2f[7] = 0;
7869
7870         if (r_hdr.integer || r_bloom.integer)
7871         {
7872                 r_bloomstate.enabled = true;
7873                 r_bloomstate.hdr = r_hdr.integer != 0;
7874         }
7875
7876         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);
7877 }
7878
7879 void R_Bloom_CopyBloomTexture(float colorscale)
7880 {
7881         r_refdef.stats.bloom++;
7882
7883         // scale down screen texture to the bloom texture size
7884         CHECKGLERROR
7885         R_SetViewport(&r_bloomstate.viewport);
7886         GL_BlendFunc(GL_ONE, GL_ZERO);
7887         GL_Color(colorscale, colorscale, colorscale, 1);
7888         // TODO: optimize with multitexture or GLSL
7889         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7890         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7891         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7892         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7893
7894         // we now have a bloom image in the framebuffer
7895         // copy it into the bloom image texture for later processing
7896         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);
7897         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7898 }
7899
7900 void R_Bloom_CopyHDRTexture(void)
7901 {
7902         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);
7903         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7904 }
7905
7906 void R_Bloom_MakeTexture(void)
7907 {
7908         int x, range, dir;
7909         float xoffset, yoffset, r, brighten;
7910
7911         r_refdef.stats.bloom++;
7912
7913         R_ResetViewRendering2D();
7914         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7915         R_Mesh_ColorPointer(NULL, 0, 0);
7916
7917         // we have a bloom image in the framebuffer
7918         CHECKGLERROR
7919         R_SetViewport(&r_bloomstate.viewport);
7920
7921         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7922         {
7923                 x *= 2;
7924                 r = bound(0, r_bloom_colorexponent.value / x, 1);
7925                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7926                 GL_Color(r, r, r, 1);
7927                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7928                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7929                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7930                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7931
7932                 // copy the vertically blurred bloom view to a texture
7933                 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);
7934                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7935         }
7936
7937         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7938         brighten = r_bloom_brighten.value;
7939         if (r_hdr.integer)
7940                 brighten *= r_hdr_range.value;
7941         brighten = sqrt(brighten);
7942         if(range >= 1)
7943                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7944         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7945         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7946
7947         for (dir = 0;dir < 2;dir++)
7948         {
7949                 // blend on at multiple vertical offsets to achieve a vertical blur
7950                 // TODO: do offset blends using GLSL
7951                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7952                 GL_BlendFunc(GL_ONE, GL_ZERO);
7953                 for (x = -range;x <= range;x++)
7954                 {
7955                         if (!dir){xoffset = 0;yoffset = x;}
7956                         else {xoffset = x;yoffset = 0;}
7957                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7958                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7959                         // compute a texcoord array with the specified x and y offset
7960                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7961                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7962                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7963                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7964                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7965                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7966                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7967                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7968                         // this r value looks like a 'dot' particle, fading sharply to
7969                         // black at the edges
7970                         // (probably not realistic but looks good enough)
7971                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7972                         //r = brighten/(range*2+1);
7973                         r = brighten / (range * 2 + 1);
7974                         if(range >= 1)
7975                                 r *= (1 - x*x/(float)(range*range));
7976                         GL_Color(r, r, r, 1);
7977                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7978                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7979                         GL_BlendFunc(GL_ONE, GL_ONE);
7980                 }
7981
7982                 // copy the vertically blurred bloom view to a texture
7983                 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);
7984                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7985         }
7986
7987         // apply subtract last
7988         // (just like it would be in a GLSL shader)
7989         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7990         {
7991                 GL_BlendFunc(GL_ONE, GL_ZERO);
7992                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7993                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7994                 GL_Color(1, 1, 1, 1);
7995                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7996                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7997
7998                 GL_BlendFunc(GL_ONE, GL_ONE);
7999                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
8000                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8001                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
8002                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
8003                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8004                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8005                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
8006
8007                 // copy the darkened bloom view to a texture
8008                 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);
8009                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8010         }
8011 }
8012
8013 void R_HDR_RenderBloomTexture(void)
8014 {
8015         int oldwidth, oldheight;
8016         float oldcolorscale;
8017
8018         oldcolorscale = r_refdef.view.colorscale;
8019         oldwidth = r_refdef.view.width;
8020         oldheight = r_refdef.view.height;
8021         r_refdef.view.width = r_bloomstate.bloomwidth;
8022         r_refdef.view.height = r_bloomstate.bloomheight;
8023
8024         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
8025         // TODO: add exposure compensation features
8026         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8027
8028         r_refdef.view.showdebug = false;
8029         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8030
8031         R_ResetViewRendering3D();
8032
8033         R_ClearScreen(r_refdef.fogenabled);
8034         if (r_timereport_active)
8035                 R_TimeReport("HDRclear");
8036
8037         R_View_Update();
8038         if (r_timereport_active)
8039                 R_TimeReport("visibility");
8040
8041         // only do secondary renders with HDR if r_hdr is 2 or higher
8042         r_waterstate.numwaterplanes = 0;
8043         if (r_waterstate.enabled && r_hdr.integer >= 2)
8044                 R_RenderWaterPlanes();
8045
8046         r_refdef.view.showdebug = true;
8047         R_RenderScene();
8048         r_waterstate.numwaterplanes = 0;
8049
8050         R_ResetViewRendering2D();
8051
8052         R_Bloom_CopyHDRTexture();
8053         R_Bloom_MakeTexture();
8054
8055         // restore the view settings
8056         r_refdef.view.width = oldwidth;
8057         r_refdef.view.height = oldheight;
8058         r_refdef.view.colorscale = oldcolorscale;
8059
8060         R_ResetViewRendering3D();
8061
8062         R_ClearScreen(r_refdef.fogenabled);
8063         if (r_timereport_active)
8064                 R_TimeReport("viewclear");
8065 }
8066
8067 static void R_BlendView(void)
8068 {
8069         unsigned int permutation;
8070         float uservecs[4][4];
8071
8072         switch (vid.renderpath)
8073         {
8074         case RENDERPATH_GL20:
8075         case RENDERPATH_CGGL:
8076                 permutation =
8077                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8078                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8079                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8080                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8081                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8082
8083                 if (r_bloomstate.texture_screen)
8084                 {
8085                         // make sure the buffer is available
8086                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8087
8088                         R_ResetViewRendering2D();
8089                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8090                         R_Mesh_ColorPointer(NULL, 0, 0);
8091
8092                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8093                         {
8094                                 // declare variables
8095                                 float speed;
8096                                 static float avgspeed;
8097
8098                                 speed = VectorLength(cl.movement_velocity);
8099
8100                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8101                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8102
8103                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8104                                 speed = bound(0, speed, 1);
8105                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8106
8107                                 // calculate values into a standard alpha
8108                                 cl.motionbluralpha = 1 - exp(-
8109                                                 (
8110                                                  (r_motionblur.value * speed / 80)
8111                                                  +
8112                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8113                                                 )
8114                                                 /
8115                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
8116                                            );
8117
8118                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8119                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8120                                 // apply the blur
8121                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8122                                 {
8123                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8124                                         GL_Color(1, 1, 1, cl.motionbluralpha);
8125                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8126                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
8127                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8128                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8129                                 }
8130                         }
8131
8132                         // copy view into the screen texture
8133                         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);
8134                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8135                 }
8136                 else if (!r_bloomstate.texture_bloom)
8137                 {
8138                         // we may still have to do view tint...
8139                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8140                         {
8141                                 // apply a color tint to the whole view
8142                                 R_ResetViewRendering2D();
8143                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8144                                 R_Mesh_ColorPointer(NULL, 0, 0);
8145                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8146                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8147                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8148                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8149                         }
8150                         break; // no screen processing, no bloom, skip it
8151                 }
8152
8153                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8154                 {
8155                         // render simple bloom effect
8156                         // copy the screen and shrink it and darken it for the bloom process
8157                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8158                         // make the bloom texture
8159                         R_Bloom_MakeTexture();
8160                 }
8161
8162 #if _MSC_VER >= 1400
8163 #define sscanf sscanf_s
8164 #endif
8165                 memset(uservecs, 0, sizeof(uservecs));
8166                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8167                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8168                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
8169                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
8170
8171                 R_ResetViewRendering2D();
8172                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8173                 R_Mesh_ColorPointer(NULL, 0, 0);
8174                 GL_Color(1, 1, 1, 1);
8175                 GL_BlendFunc(GL_ONE, GL_ZERO);
8176                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
8177                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
8178
8179                 switch(vid.renderpath)
8180                 {
8181                 case RENDERPATH_GL20:
8182                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
8183                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
8184                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
8185                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
8186                         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]);
8187                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8188                         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]);
8189                         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]);
8190                         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]);
8191                         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]);
8192                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
8193                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8194                         break;
8195                 case RENDERPATH_CGGL:
8196 #ifdef SUPPORTCG
8197                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
8198                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
8199                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
8200                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
8201                         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
8202                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
8203                         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
8204                         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
8205                         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
8206                         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
8207                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
8208                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
8209 #endif
8210                         break;
8211                 default:
8212                         break;
8213                 }
8214                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8215                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8216                 break;
8217         case RENDERPATH_GL13:
8218         case RENDERPATH_GL11:
8219                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8220                 {
8221                         // apply a color tint to the whole view
8222                         R_ResetViewRendering2D();
8223                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
8224                         R_Mesh_ColorPointer(NULL, 0, 0);
8225                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8226                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8227                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8228                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
8229                 }
8230                 break;
8231         }
8232 }
8233
8234 matrix4x4_t r_waterscrollmatrix;
8235
8236 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
8237 {
8238         if (r_refdef.fog_density)
8239         {
8240                 r_refdef.fogcolor[0] = r_refdef.fog_red;
8241                 r_refdef.fogcolor[1] = r_refdef.fog_green;
8242                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
8243
8244                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
8245                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
8246                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
8247                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
8248
8249                 {
8250                         vec3_t fogvec;
8251                         VectorCopy(r_refdef.fogcolor, fogvec);
8252                         //   color.rgb *= ContrastBoost * SceneBrightness;
8253                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
8254                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
8255                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
8256                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
8257                 }
8258         }
8259 }
8260
8261 void R_UpdateVariables(void)
8262 {
8263         R_Textures_Frame();
8264
8265         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
8266
8267         r_refdef.farclip = r_farclip_base.value;
8268         if (r_refdef.scene.worldmodel)
8269                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
8270         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
8271
8272         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8273                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8274         r_refdef.polygonfactor = 0;
8275         r_refdef.polygonoffset = 0;
8276         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8277         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8278
8279         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8280         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8281         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
8282         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8283         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8284         if (r_showsurfaces.integer)
8285         {
8286                 r_refdef.scene.rtworld = false;
8287                 r_refdef.scene.rtworldshadows = false;
8288                 r_refdef.scene.rtdlight = false;
8289                 r_refdef.scene.rtdlightshadows = false;
8290                 r_refdef.lightmapintensity = 0;
8291         }
8292
8293         if (gamemode == GAME_NEHAHRA)
8294         {
8295                 if (gl_fogenable.integer)
8296                 {
8297                         r_refdef.oldgl_fogenable = true;
8298                         r_refdef.fog_density = gl_fogdensity.value;
8299                         r_refdef.fog_red = gl_fogred.value;
8300                         r_refdef.fog_green = gl_foggreen.value;
8301                         r_refdef.fog_blue = gl_fogblue.value;
8302                         r_refdef.fog_alpha = 1;
8303                         r_refdef.fog_start = 0;
8304                         r_refdef.fog_end = gl_skyclip.value;
8305                         r_refdef.fog_height = 1<<30;
8306                         r_refdef.fog_fadedepth = 128;
8307                 }
8308                 else if (r_refdef.oldgl_fogenable)
8309                 {
8310                         r_refdef.oldgl_fogenable = false;
8311                         r_refdef.fog_density = 0;
8312                         r_refdef.fog_red = 0;
8313                         r_refdef.fog_green = 0;
8314                         r_refdef.fog_blue = 0;
8315                         r_refdef.fog_alpha = 0;
8316                         r_refdef.fog_start = 0;
8317                         r_refdef.fog_end = 0;
8318                         r_refdef.fog_height = 1<<30;
8319                         r_refdef.fog_fadedepth = 128;
8320                 }
8321         }
8322
8323         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
8324         r_refdef.fog_start = max(0, r_refdef.fog_start);
8325         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
8326
8327         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
8328
8329         if (r_refdef.fog_density && r_drawfog.integer)
8330         {
8331                 r_refdef.fogenabled = true;
8332                 // this is the point where the fog reaches 0.9986 alpha, which we
8333                 // consider a good enough cutoff point for the texture
8334                 // (0.9986 * 256 == 255.6)
8335                 if (r_fog_exp2.integer)
8336                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
8337                 else
8338                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
8339                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
8340                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
8341                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
8342                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
8343                         R_BuildFogHeightTexture();
8344                 // fog color was already set
8345                 // update the fog texture
8346                 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)
8347                         R_BuildFogTexture();
8348                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
8349                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
8350         }
8351         else
8352                 r_refdef.fogenabled = false;
8353
8354         switch(vid.renderpath)
8355         {
8356         case RENDERPATH_GL20:
8357         case RENDERPATH_CGGL:
8358                 if(v_glslgamma.integer && !vid_gammatables_trivial)
8359                 {
8360                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
8361                         {
8362                                 // build GLSL gamma texture
8363 #define RAMPWIDTH 256
8364                                 unsigned short ramp[RAMPWIDTH * 3];
8365                                 unsigned char rampbgr[RAMPWIDTH][4];
8366                                 int i;
8367
8368                                 r_texture_gammaramps_serial = vid_gammatables_serial;
8369
8370                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
8371                                 for(i = 0; i < RAMPWIDTH; ++i)
8372                                 {
8373                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8374                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8375                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
8376                                         rampbgr[i][3] = 0;
8377                                 }
8378                                 if (r_texture_gammaramps)
8379                                 {
8380                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
8381                                 }
8382                                 else
8383                                 {
8384                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
8385                                 }
8386                         }
8387                 }
8388                 else
8389                 {
8390                         // remove GLSL gamma texture
8391                 }
8392                 break;
8393         case RENDERPATH_GL13:
8394         case RENDERPATH_GL11:
8395                 break;
8396         }
8397 }
8398
8399 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
8400 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
8401 /*
8402 ================
8403 R_SelectScene
8404 ================
8405 */
8406 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
8407         if( scenetype != r_currentscenetype ) {
8408                 // store the old scenetype
8409                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
8410                 r_currentscenetype = scenetype;
8411                 // move in the new scene
8412                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
8413         }
8414 }
8415
8416 /*
8417 ================
8418 R_GetScenePointer
8419 ================
8420 */
8421 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
8422 {
8423         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
8424         if( scenetype == r_currentscenetype ) {
8425                 return &r_refdef.scene;
8426         } else {
8427                 return &r_scenes_store[ scenetype ];
8428         }
8429 }
8430
8431 /*
8432 ================
8433 R_RenderView
8434 ================
8435 */
8436 void R_RenderView(void)
8437 {
8438         if (r_timereport_active)
8439                 R_TimeReport("start");
8440         r_textureframe++; // used only by R_GetCurrentTexture
8441         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8442
8443         if (!r_drawentities.integer)
8444                 r_refdef.scene.numentities = 0;
8445
8446         R_AnimCache_ClearCache();
8447         R_FrameData_NewFrame();
8448
8449         if (r_refdef.view.isoverlay)
8450         {
8451                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
8452                 GL_Clear( GL_DEPTH_BUFFER_BIT );
8453                 R_TimeReport("depthclear");
8454
8455                 r_refdef.view.showdebug = false;
8456
8457                 r_waterstate.enabled = false;
8458                 r_waterstate.numwaterplanes = 0;
8459
8460                 R_RenderScene();
8461
8462                 CHECKGLERROR
8463                 return;
8464         }
8465
8466         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
8467                 return; //Host_Error ("R_RenderView: NULL worldmodel");
8468
8469         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
8470
8471         R_RenderView_UpdateViewVectors();
8472
8473         R_Shadow_UpdateWorldLightSelection();
8474
8475         R_Bloom_StartFrame();
8476         R_Water_StartFrame();
8477
8478         CHECKGLERROR
8479         if (r_timereport_active)
8480                 R_TimeReport("viewsetup");
8481
8482         R_ResetViewRendering3D();
8483
8484         if (r_refdef.view.clear || r_refdef.fogenabled)
8485         {
8486                 R_ClearScreen(r_refdef.fogenabled);
8487                 if (r_timereport_active)
8488                         R_TimeReport("viewclear");
8489         }
8490         r_refdef.view.clear = true;
8491
8492         // this produces a bloom texture to be used in R_BlendView() later
8493         if (r_hdr.integer && r_bloomstate.bloomwidth)
8494         {
8495                 R_HDR_RenderBloomTexture();
8496                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
8497                 r_textureframe++; // used only by R_GetCurrentTexture
8498         }
8499
8500         r_refdef.view.showdebug = true;
8501
8502         R_View_Update();
8503         if (r_timereport_active)
8504                 R_TimeReport("visibility");
8505
8506         r_waterstate.numwaterplanes = 0;
8507         if (r_waterstate.enabled)
8508                 R_RenderWaterPlanes();
8509
8510         R_RenderScene();
8511         r_waterstate.numwaterplanes = 0;
8512
8513         R_BlendView();
8514         if (r_timereport_active)
8515                 R_TimeReport("blendview");
8516
8517         GL_Scissor(0, 0, vid.width, vid.height);
8518         GL_ScissorTest(false);
8519         CHECKGLERROR
8520 }
8521
8522 void R_RenderWaterPlanes(void)
8523 {
8524         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
8525         {
8526                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
8527                 if (r_timereport_active)
8528                         R_TimeReport("waterworld");
8529         }
8530
8531         // don't let sound skip if going slow
8532         if (r_refdef.scene.extraupdate)
8533                 S_ExtraUpdate ();
8534
8535         R_DrawModelsAddWaterPlanes();
8536         if (r_timereport_active)
8537                 R_TimeReport("watermodels");
8538
8539         if (r_waterstate.numwaterplanes)
8540         {
8541                 R_Water_ProcessPlanes();
8542                 if (r_timereport_active)
8543                         R_TimeReport("waterscenes");
8544         }
8545 }
8546
8547 extern void R_DrawLightningBeams (void);
8548 extern void VM_CL_AddPolygonsToMeshQueue (void);
8549 extern void R_DrawPortals (void);
8550 extern cvar_t cl_locs_show;
8551 static void R_DrawLocs(void);
8552 static void R_DrawEntityBBoxes(void);
8553 static void R_DrawModelDecals(void);
8554 extern void R_DrawModelShadows(void);
8555 extern void R_DrawModelShadowMaps(void);
8556 extern cvar_t cl_decals_newsystem;
8557 extern qboolean r_shadow_usingdeferredprepass;
8558 void R_RenderScene(void)
8559 {
8560         qboolean shadowmapping = false;
8561
8562         if (r_timereport_active)
8563                 R_TimeReport("beginscene");
8564
8565         r_refdef.stats.renders++;
8566
8567         R_UpdateFogColor();
8568
8569         // don't let sound skip if going slow
8570         if (r_refdef.scene.extraupdate)
8571                 S_ExtraUpdate ();
8572
8573         R_MeshQueue_BeginScene();
8574
8575         R_SkyStartFrame();
8576
8577         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);
8578
8579         if (r_timereport_active)
8580                 R_TimeReport("skystartframe");
8581
8582         if (cl.csqc_vidvars.drawworld)
8583         {
8584                 // don't let sound skip if going slow
8585                 if (r_refdef.scene.extraupdate)
8586                         S_ExtraUpdate ();
8587
8588                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
8589                 {
8590                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
8591                         if (r_timereport_active)
8592                                 R_TimeReport("worldsky");
8593                 }
8594
8595                 if (R_DrawBrushModelsSky() && r_timereport_active)
8596                         R_TimeReport("bmodelsky");
8597
8598                 if (skyrendermasked && skyrenderlater)
8599                 {
8600                         // we have to force off the water clipping plane while rendering sky
8601                         R_SetupView(false);
8602                         R_Sky();
8603                         R_SetupView(true);
8604                         if (r_timereport_active)
8605                                 R_TimeReport("sky");
8606                 }
8607         }
8608
8609         R_AnimCache_CacheVisibleEntities();
8610         if (r_timereport_active)
8611                 R_TimeReport("animation");
8612
8613         R_Shadow_PrepareLights();
8614         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
8615                 R_Shadow_PrepareModelShadows();
8616         if (r_timereport_active)
8617                 R_TimeReport("preparelights");
8618
8619         if (R_Shadow_ShadowMappingEnabled())
8620                 shadowmapping = true;
8621
8622         if (r_shadow_usingdeferredprepass)
8623                 R_Shadow_DrawPrepass();
8624
8625         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
8626         {
8627                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
8628                 if (r_timereport_active)
8629                         R_TimeReport("worlddepth");
8630         }
8631         if (r_depthfirst.integer >= 2)
8632         {
8633                 R_DrawModelsDepth();
8634                 if (r_timereport_active)
8635                         R_TimeReport("modeldepth");
8636         }
8637
8638         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
8639         {
8640                 R_DrawModelShadowMaps();
8641                 R_ResetViewRendering3D();
8642                 // don't let sound skip if going slow
8643                 if (r_refdef.scene.extraupdate)
8644                         S_ExtraUpdate ();
8645         }
8646
8647         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
8648         {
8649                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
8650                 if (r_timereport_active)
8651                         R_TimeReport("world");
8652         }
8653
8654         // don't let sound skip if going slow
8655         if (r_refdef.scene.extraupdate)
8656                 S_ExtraUpdate ();
8657
8658         R_DrawModels();
8659         if (r_timereport_active)
8660                 R_TimeReport("models");
8661
8662         // don't let sound skip if going slow
8663         if (r_refdef.scene.extraupdate)
8664                 S_ExtraUpdate ();
8665
8666         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8667         {
8668                 R_DrawModelShadows();
8669                 R_ResetViewRendering3D();
8670                 // don't let sound skip if going slow
8671                 if (r_refdef.scene.extraupdate)
8672                         S_ExtraUpdate ();
8673         }
8674
8675         if (!r_shadow_usingdeferredprepass)
8676         {
8677                 R_Shadow_DrawLights();
8678                 if (r_timereport_active)
8679                         R_TimeReport("rtlights");
8680         }
8681
8682         // don't let sound skip if going slow
8683         if (r_refdef.scene.extraupdate)
8684                 S_ExtraUpdate ();
8685
8686         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8687         {
8688                 R_DrawModelShadows();
8689                 R_ResetViewRendering3D();
8690                 // don't let sound skip if going slow
8691                 if (r_refdef.scene.extraupdate)
8692                         S_ExtraUpdate ();
8693         }
8694
8695         if (cl.csqc_vidvars.drawworld)
8696         {
8697                 if (cl_decals_newsystem.integer)
8698                 {
8699                         R_DrawModelDecals();
8700                         if (r_timereport_active)
8701                                 R_TimeReport("modeldecals");
8702                 }
8703                 else
8704                 {
8705                         R_DrawDecals();
8706                         if (r_timereport_active)
8707                                 R_TimeReport("decals");
8708                 }
8709
8710                 R_DrawParticles();
8711                 if (r_timereport_active)
8712                         R_TimeReport("particles");
8713
8714                 R_DrawExplosions();
8715                 if (r_timereport_active)
8716                         R_TimeReport("explosions");
8717
8718                 R_DrawLightningBeams();
8719                 if (r_timereport_active)
8720                         R_TimeReport("lightning");
8721         }
8722
8723         VM_CL_AddPolygonsToMeshQueue();
8724
8725         if (r_refdef.view.showdebug)
8726         {
8727                 if (cl_locs_show.integer)
8728                 {
8729                         R_DrawLocs();
8730                         if (r_timereport_active)
8731                                 R_TimeReport("showlocs");
8732                 }
8733
8734                 if (r_drawportals.integer)
8735                 {
8736                         R_DrawPortals();
8737                         if (r_timereport_active)
8738                                 R_TimeReport("portals");
8739                 }
8740
8741                 if (r_showbboxes.value > 0)
8742                 {
8743                         R_DrawEntityBBoxes();
8744                         if (r_timereport_active)
8745                                 R_TimeReport("bboxes");
8746                 }
8747         }
8748
8749         R_MeshQueue_RenderTransparent();
8750         if (r_timereport_active)
8751                 R_TimeReport("drawtrans");
8752
8753         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))
8754         {
8755                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8756                 if (r_timereport_active)
8757                         R_TimeReport("worlddebug");
8758                 R_DrawModelsDebug();
8759                 if (r_timereport_active)
8760                         R_TimeReport("modeldebug");
8761         }
8762
8763         if (cl.csqc_vidvars.drawworld)
8764         {
8765                 R_Shadow_DrawCoronas();
8766                 if (r_timereport_active)
8767                         R_TimeReport("coronas");
8768         }
8769
8770         // don't let sound skip if going slow
8771         if (r_refdef.scene.extraupdate)
8772                 S_ExtraUpdate ();
8773
8774         R_ResetViewRendering2D();
8775 }
8776
8777 static const unsigned short bboxelements[36] =
8778 {
8779         5, 1, 3, 5, 3, 7,
8780         6, 2, 0, 6, 0, 4,
8781         7, 3, 2, 7, 2, 6,
8782         4, 0, 1, 4, 1, 5,
8783         4, 5, 7, 4, 7, 6,
8784         1, 0, 2, 1, 2, 3,
8785 };
8786
8787 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8788 {
8789         int i;
8790         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8791
8792         RSurf_ActiveWorldEntity();
8793
8794         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8795         GL_DepthMask(false);
8796         GL_DepthRange(0, 1);
8797         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8798         R_Mesh_ResetTextureState();
8799
8800         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8801         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8802         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8803         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8804         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8805         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8806         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8807         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8808         R_FillColors(color4f, 8, cr, cg, cb, ca);
8809         if (r_refdef.fogenabled)
8810         {
8811                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8812                 {
8813                         f1 = RSurf_FogVertex(v);
8814                         f2 = 1 - f1;
8815                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8816                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8817                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8818                 }
8819         }
8820         R_Mesh_VertexPointer(vertex3f, 0, 0);
8821         R_Mesh_ColorPointer(color4f, 0, 0);
8822         R_Mesh_ResetTextureState();
8823         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8824         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8825 }
8826
8827 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8828 {
8829         int i;
8830         float color[4];
8831         prvm_edict_t *edict;
8832         prvm_prog_t *prog_save = prog;
8833
8834         // this function draws bounding boxes of server entities
8835         if (!sv.active)
8836                 return;
8837
8838         GL_CullFace(GL_NONE);
8839         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8840
8841         prog = 0;
8842         SV_VM_Begin();
8843         for (i = 0;i < numsurfaces;i++)
8844         {
8845                 edict = PRVM_EDICT_NUM(surfacelist[i]);
8846                 switch ((int)edict->fields.server->solid)
8847                 {
8848                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
8849                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
8850                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
8851                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8852                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
8853                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
8854                 }
8855                 color[3] *= r_showbboxes.value;
8856                 color[3] = bound(0, color[3], 1);
8857                 GL_DepthTest(!r_showdisabledepthtest.integer);
8858                 GL_CullFace(r_refdef.view.cullface_front);
8859                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8860         }
8861         SV_VM_End();
8862         prog = prog_save;
8863 }
8864
8865 static void R_DrawEntityBBoxes(void)
8866 {
8867         int i;
8868         prvm_edict_t *edict;
8869         vec3_t center;
8870         prvm_prog_t *prog_save = prog;
8871
8872         // this function draws bounding boxes of server entities
8873         if (!sv.active)
8874                 return;
8875
8876         prog = 0;
8877         SV_VM_Begin();
8878         for (i = 0;i < prog->num_edicts;i++)
8879         {
8880                 edict = PRVM_EDICT_NUM(i);
8881                 if (edict->priv.server->free)
8882                         continue;
8883                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8884                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8885                         continue;
8886                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8887                         continue;
8888                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8889                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8890         }
8891         SV_VM_End();
8892         prog = prog_save;
8893 }
8894
8895 static const int nomodelelement3i[24] =
8896 {
8897         5, 2, 0,
8898         5, 1, 2,
8899         5, 0, 3,
8900         5, 3, 1,
8901         0, 2, 4,
8902         2, 1, 4,
8903         3, 0, 4,
8904         1, 3, 4
8905 };
8906
8907 static const unsigned short nomodelelement3s[24] =
8908 {
8909         5, 2, 0,
8910         5, 1, 2,
8911         5, 0, 3,
8912         5, 3, 1,
8913         0, 2, 4,
8914         2, 1, 4,
8915         3, 0, 4,
8916         1, 3, 4
8917 };
8918
8919 static const float nomodelvertex3f[6*3] =
8920 {
8921         -16,   0,   0,
8922          16,   0,   0,
8923           0, -16,   0,
8924           0,  16,   0,
8925           0,   0, -16,
8926           0,   0,  16
8927 };
8928
8929 static const float nomodelcolor4f[6*4] =
8930 {
8931         0.0f, 0.0f, 0.5f, 1.0f,
8932         0.0f, 0.0f, 0.5f, 1.0f,
8933         0.0f, 0.5f, 0.0f, 1.0f,
8934         0.0f, 0.5f, 0.0f, 1.0f,
8935         0.5f, 0.0f, 0.0f, 1.0f,
8936         0.5f, 0.0f, 0.0f, 1.0f
8937 };
8938
8939 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8940 {
8941         int i;
8942         float f1, f2, *c;
8943         float color4f[6*4];
8944
8945         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);
8946
8947         // this is only called once per entity so numsurfaces is always 1, and
8948         // surfacelist is always {0}, so this code does not handle batches
8949
8950         if (rsurface.ent_flags & RENDER_ADDITIVE)
8951         {
8952                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8953                 GL_DepthMask(false);
8954         }
8955         else if (rsurface.colormod[3] < 1)
8956         {
8957                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8958                 GL_DepthMask(false);
8959         }
8960         else
8961         {
8962                 GL_BlendFunc(GL_ONE, GL_ZERO);
8963                 GL_DepthMask(true);
8964         }
8965         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8966         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8967         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8968         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8969         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8970         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8971         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8972         R_Mesh_ColorPointer(color4f, 0, 0);
8973         for (i = 0, c = color4f;i < 6;i++, c += 4)
8974         {
8975                 c[0] *= rsurface.colormod[0];
8976                 c[1] *= rsurface.colormod[1];
8977                 c[2] *= rsurface.colormod[2];
8978                 c[3] *= rsurface.colormod[3];
8979         }
8980         if (r_refdef.fogenabled)
8981         {
8982                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8983                 {
8984                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8985                         f2 = 1 - f1;
8986                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8987                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8988                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8989                 }
8990         }
8991         R_Mesh_ResetTextureState();
8992         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8993 }
8994
8995 void R_DrawNoModel(entity_render_t *ent)
8996 {
8997         vec3_t org;
8998         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8999         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9000                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9001         else
9002                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9003 }
9004
9005 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9006 {
9007         vec3_t right1, right2, diff, normal;
9008
9009         VectorSubtract (org2, org1, normal);
9010
9011         // calculate 'right' vector for start
9012         VectorSubtract (r_refdef.view.origin, org1, diff);
9013         CrossProduct (normal, diff, right1);
9014         VectorNormalize (right1);
9015
9016         // calculate 'right' vector for end
9017         VectorSubtract (r_refdef.view.origin, org2, diff);
9018         CrossProduct (normal, diff, right2);
9019         VectorNormalize (right2);
9020
9021         vert[ 0] = org1[0] + width * right1[0];
9022         vert[ 1] = org1[1] + width * right1[1];
9023         vert[ 2] = org1[2] + width * right1[2];
9024         vert[ 3] = org1[0] - width * right1[0];
9025         vert[ 4] = org1[1] - width * right1[1];
9026         vert[ 5] = org1[2] - width * right1[2];
9027         vert[ 6] = org2[0] - width * right2[0];
9028         vert[ 7] = org2[1] - width * right2[1];
9029         vert[ 8] = org2[2] - width * right2[2];
9030         vert[ 9] = org2[0] + width * right2[0];
9031         vert[10] = org2[1] + width * right2[1];
9032         vert[11] = org2[2] + width * right2[2];
9033 }
9034
9035 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)
9036 {
9037         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9038         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9039         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9040         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9041         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9042         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9043         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9044         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9045         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9046         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9047         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9048         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9049 }
9050
9051 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9052 {
9053         int i;
9054         float *vertex3f;
9055         float v[3];
9056         VectorSet(v, x, y, z);
9057         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9058                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9059                         break;
9060         if (i == mesh->numvertices)
9061         {
9062                 if (mesh->numvertices < mesh->maxvertices)
9063                 {
9064                         VectorCopy(v, vertex3f);
9065                         mesh->numvertices++;
9066                 }
9067                 return mesh->numvertices;
9068         }
9069         else
9070                 return i;
9071 }
9072
9073 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9074 {
9075         int i;
9076         int *e, element[3];
9077         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9078         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9079         e = mesh->element3i + mesh->numtriangles * 3;
9080         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9081         {
9082                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9083                 if (mesh->numtriangles < mesh->maxtriangles)
9084                 {
9085                         *e++ = element[0];
9086                         *e++ = element[1];
9087                         *e++ = element[2];
9088                         mesh->numtriangles++;
9089                 }
9090                 element[1] = element[2];
9091         }
9092 }
9093
9094 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9095 {
9096         int i;
9097         int *e, element[3];
9098         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9099         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9100         e = mesh->element3i + mesh->numtriangles * 3;
9101         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9102         {
9103                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9104                 if (mesh->numtriangles < mesh->maxtriangles)
9105                 {
9106                         *e++ = element[0];
9107                         *e++ = element[1];
9108                         *e++ = element[2];
9109                         mesh->numtriangles++;
9110                 }
9111                 element[1] = element[2];
9112         }
9113 }
9114
9115 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9116 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9117 {
9118         int planenum, planenum2;
9119         int w;
9120         int tempnumpoints;
9121         mplane_t *plane, *plane2;
9122         double maxdist;
9123         double temppoints[2][256*3];
9124         // figure out how large a bounding box we need to properly compute this brush
9125         maxdist = 0;
9126         for (w = 0;w < numplanes;w++)
9127                 maxdist = max(maxdist, fabs(planes[w].dist));
9128         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9129         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9130         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9131         {
9132                 w = 0;
9133                 tempnumpoints = 4;
9134                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9135                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9136                 {
9137                         if (planenum2 == planenum)
9138                                 continue;
9139                         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);
9140                         w = !w;
9141                 }
9142                 if (tempnumpoints < 3)
9143                         continue;
9144                 // generate elements forming a triangle fan for this polygon
9145                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
9146         }
9147 }
9148
9149 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)
9150 {
9151         texturelayer_t *layer;
9152         layer = t->currentlayers + t->currentnumlayers++;
9153         layer->type = type;
9154         layer->depthmask = depthmask;
9155         layer->blendfunc1 = blendfunc1;
9156         layer->blendfunc2 = blendfunc2;
9157         layer->texture = texture;
9158         layer->texmatrix = *matrix;
9159         layer->color[0] = r;
9160         layer->color[1] = g;
9161         layer->color[2] = b;
9162         layer->color[3] = a;
9163 }
9164
9165 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
9166 {
9167         double index, f;
9168         index = parms[2] + r_refdef.scene.time * parms[3];
9169         index -= floor(index);
9170         switch (func)
9171         {
9172         default:
9173         case Q3WAVEFUNC_NONE:
9174         case Q3WAVEFUNC_NOISE:
9175         case Q3WAVEFUNC_COUNT:
9176                 f = 0;
9177                 break;
9178         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
9179         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
9180         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
9181         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
9182         case Q3WAVEFUNC_TRIANGLE:
9183                 index *= 4;
9184                 f = index - floor(index);
9185                 if (index < 1)
9186                         f = f;
9187                 else if (index < 2)
9188                         f = 1 - f;
9189                 else if (index < 3)
9190                         f = -f;
9191                 else
9192                         f = -(1 - f);
9193                 break;
9194         }
9195         return (float)(parms[0] + parms[1] * f);
9196 }
9197
9198 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
9199 {
9200         int w, h, idx;
9201         float f;
9202         float tcmat[12];
9203         matrix4x4_t matrix, temp;
9204         switch(tcmod->tcmod)
9205         {
9206                 case Q3TCMOD_COUNT:
9207                 case Q3TCMOD_NONE:
9208                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9209                                 matrix = r_waterscrollmatrix;
9210                         else
9211                                 matrix = identitymatrix;
9212                         break;
9213                 case Q3TCMOD_ENTITYTRANSLATE:
9214                         // this is used in Q3 to allow the gamecode to control texcoord
9215                         // scrolling on the entity, which is not supported in darkplaces yet.
9216                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
9217                         break;
9218                 case Q3TCMOD_ROTATE:
9219                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
9220                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
9221                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
9222                         break;
9223                 case Q3TCMOD_SCALE:
9224                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
9225                         break;
9226                 case Q3TCMOD_SCROLL:
9227                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
9228                         break;
9229                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
9230                         w = (int) tcmod->parms[0];
9231                         h = (int) tcmod->parms[1];
9232                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
9233                         f = f - floor(f);
9234                         idx = (int) floor(f * w * h);
9235                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
9236                         break;
9237                 case Q3TCMOD_STRETCH:
9238                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
9239                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
9240                         break;
9241                 case Q3TCMOD_TRANSFORM:
9242                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
9243                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
9244                         VectorSet(tcmat +  6, 0                   , 0                , 1);
9245                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
9246                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
9247                         break;
9248                 case Q3TCMOD_TURBULENT:
9249                         // this is handled in the RSurf_PrepareVertices function
9250                         matrix = identitymatrix;
9251                         break;
9252         }
9253         temp = *texmatrix;
9254         Matrix4x4_Concat(texmatrix, &matrix, &temp);
9255 }
9256
9257 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
9258 {
9259         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
9260         char name[MAX_QPATH];
9261         skinframe_t *skinframe;
9262         unsigned char pixels[296*194];
9263         strlcpy(cache->name, skinname, sizeof(cache->name));
9264         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
9265         if (developer_loading.integer)
9266                 Con_Printf("loading %s\n", name);
9267         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
9268         if (!skinframe || !skinframe->base)
9269         {
9270                 unsigned char *f;
9271                 fs_offset_t filesize;
9272                 skinframe = NULL;
9273                 f = FS_LoadFile(name, tempmempool, true, &filesize);
9274                 if (f)
9275                 {
9276                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
9277                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
9278                         Mem_Free(f);
9279                 }
9280         }
9281         cache->skinframe = skinframe;
9282 }
9283
9284 texture_t *R_GetCurrentTexture(texture_t *t)
9285 {
9286         int i;
9287         const entity_render_t *ent = rsurface.entity;
9288         dp_model_t *model = ent->model;
9289         q3shaderinfo_layer_tcmod_t *tcmod;
9290
9291         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
9292                 return t->currentframe;
9293         t->update_lastrenderframe = r_textureframe;
9294         t->update_lastrenderentity = (void *)ent;
9295
9296         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
9297                 t->camera_entity = ent->entitynumber;
9298         else
9299                 t->camera_entity = 0;
9300
9301         // switch to an alternate material if this is a q1bsp animated material
9302         {
9303                 texture_t *texture = t;
9304                 int s = rsurface.ent_skinnum;
9305                 if ((unsigned int)s >= (unsigned int)model->numskins)
9306                         s = 0;
9307                 if (model->skinscenes)
9308                 {
9309                         if (model->skinscenes[s].framecount > 1)
9310                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
9311                         else
9312                                 s = model->skinscenes[s].firstframe;
9313                 }
9314                 if (s > 0)
9315                         t = t + s * model->num_surfaces;
9316                 if (t->animated)
9317                 {
9318                         // use an alternate animation if the entity's frame is not 0,
9319                         // and only if the texture has an alternate animation
9320                         if (rsurface.ent_alttextures && t->anim_total[1])
9321                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
9322                         else
9323                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
9324                 }
9325                 texture->currentframe = t;
9326         }
9327
9328         // update currentskinframe to be a qw skin or animation frame
9329         if (rsurface.ent_qwskin >= 0)
9330         {
9331                 i = rsurface.ent_qwskin;
9332                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
9333                 {
9334                         r_qwskincache_size = cl.maxclients;
9335                         if (r_qwskincache)
9336                                 Mem_Free(r_qwskincache);
9337                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
9338                 }
9339                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
9340                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
9341                 t->currentskinframe = r_qwskincache[i].skinframe;
9342                 if (t->currentskinframe == NULL)
9343                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9344         }
9345         else if (t->numskinframes >= 2)
9346                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9347         if (t->backgroundnumskinframes >= 2)
9348                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
9349
9350         t->currentmaterialflags = t->basematerialflags;
9351         t->currentalpha = rsurface.colormod[3];
9352         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
9353                 t->currentalpha *= r_wateralpha.value;
9354         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
9355                 t->currentalpha *= t->r_water_wateralpha;
9356         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
9357                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
9358         if (!(rsurface.ent_flags & RENDER_LIGHT))
9359                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
9360         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
9361         {
9362                 // pick a model lighting mode
9363                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
9364                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
9365                 else
9366                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
9367         }
9368         if (rsurface.ent_flags & RENDER_ADDITIVE)
9369                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9370         else if (t->currentalpha < 1)
9371                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9372         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
9373                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
9374         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
9375                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
9376         if (t->backgroundnumskinframes)
9377                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
9378         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
9379         {
9380                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
9381                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
9382         }
9383         else
9384                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
9385         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
9386                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
9387
9388         // there is no tcmod
9389         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9390         {
9391                 t->currenttexmatrix = r_waterscrollmatrix;
9392                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
9393         }
9394         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
9395         {
9396                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
9397                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
9398         }
9399
9400         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9401                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
9402         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9403                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
9404
9405         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
9406         if (t->currentskinframe->qpixels)
9407                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
9408         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
9409         if (!t->basetexture)
9410                 t->basetexture = r_texture_notexture;
9411         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
9412         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
9413         t->nmaptexture = t->currentskinframe->nmap;
9414         if (!t->nmaptexture)
9415                 t->nmaptexture = r_texture_blanknormalmap;
9416         t->glosstexture = r_texture_black;
9417         t->glowtexture = t->currentskinframe->glow;
9418         t->fogtexture = t->currentskinframe->fog;
9419         t->reflectmasktexture = t->currentskinframe->reflect;
9420         if (t->backgroundnumskinframes)
9421         {
9422                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
9423                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
9424                 t->backgroundglosstexture = r_texture_black;
9425                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
9426                 if (!t->backgroundnmaptexture)
9427                         t->backgroundnmaptexture = r_texture_blanknormalmap;
9428         }
9429         else
9430         {
9431                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
9432                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9433                 t->backgroundglosstexture = r_texture_black;
9434                 t->backgroundglowtexture = NULL;
9435         }
9436         t->specularpower = r_shadow_glossexponent.value;
9437         // TODO: store reference values for these in the texture?
9438         t->specularscale = 0;
9439         if (r_shadow_gloss.integer > 0)
9440         {
9441                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
9442                 {
9443                         if (r_shadow_glossintensity.value > 0)
9444                         {
9445                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
9446                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
9447                                 t->specularscale = r_shadow_glossintensity.value;
9448                         }
9449                 }
9450                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
9451                 {
9452                         t->glosstexture = r_texture_white;
9453                         t->backgroundglosstexture = r_texture_white;
9454                         t->specularscale = r_shadow_gloss2intensity.value;
9455                         t->specularpower = r_shadow_gloss2exponent.value;
9456                 }
9457         }
9458         t->specularscale *= t->specularscalemod;
9459         t->specularpower *= t->specularpowermod;
9460
9461         // lightmaps mode looks bad with dlights using actual texturing, so turn
9462         // off the colormap and glossmap, but leave the normalmap on as it still
9463         // accurately represents the shading involved
9464         if (gl_lightmaps.integer)
9465         {
9466                 t->basetexture = r_texture_grey128;
9467                 t->pantstexture = r_texture_black;
9468                 t->shirttexture = r_texture_black;
9469                 t->nmaptexture = r_texture_blanknormalmap;
9470                 t->glosstexture = r_texture_black;
9471                 t->glowtexture = NULL;
9472                 t->fogtexture = NULL;
9473                 t->reflectmasktexture = NULL;
9474                 t->backgroundbasetexture = NULL;
9475                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9476                 t->backgroundglosstexture = r_texture_black;
9477                 t->backgroundglowtexture = NULL;
9478                 t->specularscale = 0;
9479                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
9480         }
9481
9482         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
9483         VectorClear(t->dlightcolor);
9484         t->currentnumlayers = 0;
9485         if (t->currentmaterialflags & MATERIALFLAG_WALL)
9486         {
9487                 int blendfunc1, blendfunc2;
9488                 qboolean depthmask;
9489                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
9490                 {
9491                         blendfunc1 = GL_SRC_ALPHA;
9492                         blendfunc2 = GL_ONE;
9493                 }
9494                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
9495                 {
9496                         blendfunc1 = GL_SRC_ALPHA;
9497                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
9498                 }
9499                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9500                 {
9501                         blendfunc1 = t->customblendfunc[0];
9502                         blendfunc2 = t->customblendfunc[1];
9503                 }
9504                 else
9505                 {
9506                         blendfunc1 = GL_ONE;
9507                         blendfunc2 = GL_ZERO;
9508                 }
9509                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
9510                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9511                 {
9512                         // fullbright is not affected by r_refdef.lightmapintensity
9513                         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]);
9514                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9515                                 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]);
9516                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9517                                 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]);
9518                 }
9519                 else
9520                 {
9521                         vec3_t ambientcolor;
9522                         float colorscale;
9523                         // set the color tint used for lights affecting this surface
9524                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
9525                         colorscale = 2;
9526                         // q3bsp has no lightmap updates, so the lightstylevalue that
9527                         // would normally be baked into the lightmap must be
9528                         // applied to the color
9529                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
9530                         if (model->type == mod_brushq3)
9531                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
9532                         colorscale *= r_refdef.lightmapintensity;
9533                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
9534                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
9535                         // basic lit geometry
9536                         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]);
9537                         // add pants/shirt if needed
9538                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9539                                 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]);
9540                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9541                                 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]);
9542                         // now add ambient passes if needed
9543                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
9544                         {
9545                                 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]);
9546                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9547                                         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]);
9548                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9549                                         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]);
9550                         }
9551                 }
9552                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
9553                         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]);
9554                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
9555                 {
9556                         // if this is opaque use alpha blend which will darken the earlier
9557                         // passes cheaply.
9558                         //
9559                         // if this is an alpha blended material, all the earlier passes
9560                         // were darkened by fog already, so we only need to add the fog
9561                         // color ontop through the fog mask texture
9562                         //
9563                         // if this is an additive blended material, all the earlier passes
9564                         // were darkened by fog already, and we should not add fog color
9565                         // (because the background was not darkened, there is no fog color
9566                         // that was lost behind it).
9567                         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]);
9568                 }
9569         }
9570
9571         return t->currentframe;
9572 }
9573
9574 rsurfacestate_t rsurface;
9575
9576 void R_Mesh_ResizeArrays(int newvertices)
9577 {
9578         float *base;
9579         if (rsurface.array_size >= newvertices)
9580                 return;
9581         if (rsurface.array_modelvertex3f)
9582                 Mem_Free(rsurface.array_modelvertex3f);
9583         rsurface.array_size = (newvertices + 1023) & ~1023;
9584         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
9585         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
9586         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
9587         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
9588         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
9589         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
9590         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
9591         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
9592         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
9593         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
9594         rsurface.array_color4f           = base + rsurface.array_size * 27;
9595         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
9596 }
9597
9598 void RSurf_ActiveWorldEntity(void)
9599 {
9600         dp_model_t *model = r_refdef.scene.worldmodel;
9601         //if (rsurface.entity == r_refdef.scene.worldentity)
9602         //      return;
9603         rsurface.entity = r_refdef.scene.worldentity;
9604         rsurface.skeleton = NULL;
9605         rsurface.ent_skinnum = 0;
9606         rsurface.ent_qwskin = -1;
9607         rsurface.ent_shadertime = 0;
9608         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
9609         if (rsurface.array_size < model->surfmesh.num_vertices)
9610                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9611         rsurface.matrix = identitymatrix;
9612         rsurface.inversematrix = identitymatrix;
9613         rsurface.matrixscale = 1;
9614         rsurface.inversematrixscale = 1;
9615         R_EntityMatrix(&identitymatrix);
9616         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
9617         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
9618         rsurface.fograngerecip = r_refdef.fograngerecip;
9619         rsurface.fogheightfade = r_refdef.fogheightfade;
9620         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
9621         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9622         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9623         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9624         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9625         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9626         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9627         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
9628         rsurface.colormod[3] = 1;
9629         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);
9630         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9631         rsurface.frameblend[0].lerp = 1;
9632         rsurface.ent_alttextures = false;
9633         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9634         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9635         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9636         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9637         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9638         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9639         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9640         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9641         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9642         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9643         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9644         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9645         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9646         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9647         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9648         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9649         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9650         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9651         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9652         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9653         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9654         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9655         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9656         rsurface.modelelement3i = model->surfmesh.data_element3i;
9657         rsurface.modelelement3s = model->surfmesh.data_element3s;
9658         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9659         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9660         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9661         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9662         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9663         rsurface.modelsurfaces = model->data_surfaces;
9664         rsurface.generatedvertex = false;
9665         rsurface.vertex3f  = rsurface.modelvertex3f;
9666         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9667         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9668         rsurface.svector3f = rsurface.modelsvector3f;
9669         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9670         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9671         rsurface.tvector3f = rsurface.modeltvector3f;
9672         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9673         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9674         rsurface.normal3f  = rsurface.modelnormal3f;
9675         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9676         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9677         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9678 }
9679
9680 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
9681 {
9682         dp_model_t *model = ent->model;
9683         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
9684         //      return;
9685         rsurface.entity = (entity_render_t *)ent;
9686         rsurface.skeleton = ent->skeleton;
9687         rsurface.ent_skinnum = ent->skinnum;
9688         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;
9689         rsurface.ent_shadertime = ent->shadertime;
9690         rsurface.ent_flags = ent->flags;
9691         if (rsurface.array_size < model->surfmesh.num_vertices)
9692                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9693         rsurface.matrix = ent->matrix;
9694         rsurface.inversematrix = ent->inversematrix;
9695         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9696         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9697         R_EntityMatrix(&rsurface.matrix);
9698         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9699         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9700         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9701         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9702         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9703         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9704         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9705         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9706         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9707         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9708         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9709         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9710         rsurface.colormod[3] = ent->alpha;
9711         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9712         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9713         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9714         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9715         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9716         if (ent->model->brush.submodel && !prepass)
9717         {
9718                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9719                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9720         }
9721         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9722         {
9723                 if (ent->animcache_vertex3f && !r_framedata_failed)
9724                 {
9725                         rsurface.modelvertex3f = ent->animcache_vertex3f;
9726                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9727                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9728                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9729                 }
9730                 else if (wanttangents)
9731                 {
9732                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9733                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9734                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9735                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9736                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9737                 }
9738                 else if (wantnormals)
9739                 {
9740                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9741                         rsurface.modelsvector3f = NULL;
9742                         rsurface.modeltvector3f = NULL;
9743                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9744                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9745                 }
9746                 else
9747                 {
9748                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9749                         rsurface.modelsvector3f = NULL;
9750                         rsurface.modeltvector3f = NULL;
9751                         rsurface.modelnormal3f = NULL;
9752                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9753                 }
9754                 rsurface.modelvertex3f_bufferobject = 0;
9755                 rsurface.modelvertex3f_bufferoffset = 0;
9756                 rsurface.modelsvector3f_bufferobject = 0;
9757                 rsurface.modelsvector3f_bufferoffset = 0;
9758                 rsurface.modeltvector3f_bufferobject = 0;
9759                 rsurface.modeltvector3f_bufferoffset = 0;
9760                 rsurface.modelnormal3f_bufferobject = 0;
9761                 rsurface.modelnormal3f_bufferoffset = 0;
9762                 rsurface.generatedvertex = true;
9763         }
9764         else
9765         {
9766                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9767                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9768                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9769                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9770                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9771                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9772                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9773                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9774                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9775                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9776                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9777                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9778                 rsurface.generatedvertex = false;
9779         }
9780         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9781         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9782         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9783         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9784         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9785         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9786         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9787         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9788         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9789         rsurface.modelelement3i = model->surfmesh.data_element3i;
9790         rsurface.modelelement3s = model->surfmesh.data_element3s;
9791         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9792         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9793         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9794         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9795         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9796         rsurface.modelsurfaces = model->data_surfaces;
9797         rsurface.vertex3f  = rsurface.modelvertex3f;
9798         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9799         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9800         rsurface.svector3f = rsurface.modelsvector3f;
9801         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9802         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9803         rsurface.tvector3f = rsurface.modeltvector3f;
9804         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9805         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9806         rsurface.normal3f  = rsurface.modelnormal3f;
9807         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9808         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9809         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9810 }
9811
9812 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)
9813 {
9814         rsurface.entity = r_refdef.scene.worldentity;
9815         rsurface.skeleton = NULL;
9816         rsurface.ent_skinnum = 0;
9817         rsurface.ent_qwskin = -1;
9818         rsurface.ent_shadertime = shadertime;
9819         rsurface.ent_flags = entflags;
9820         rsurface.modelnum_vertices = numvertices;
9821         rsurface.modelnum_triangles = numtriangles;
9822         if (rsurface.array_size < rsurface.modelnum_vertices)
9823                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9824         rsurface.matrix = *matrix;
9825         rsurface.inversematrix = *inversematrix;
9826         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9827         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9828         R_EntityMatrix(&rsurface.matrix);
9829         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9830         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9831         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9832         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9833         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9834         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9835         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9836         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9837         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9838         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9839         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9840         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9841         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);
9842         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9843         rsurface.frameblend[0].lerp = 1;
9844         rsurface.ent_alttextures = false;
9845         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9846         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9847         if (wanttangents)
9848         {
9849                 rsurface.modelvertex3f = vertex3f;
9850                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9851                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9852                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9853         }
9854         else if (wantnormals)
9855         {
9856                 rsurface.modelvertex3f = vertex3f;
9857                 rsurface.modelsvector3f = NULL;
9858                 rsurface.modeltvector3f = NULL;
9859                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9860         }
9861         else
9862         {
9863                 rsurface.modelvertex3f = vertex3f;
9864                 rsurface.modelsvector3f = NULL;
9865                 rsurface.modeltvector3f = NULL;
9866                 rsurface.modelnormal3f = NULL;
9867         }
9868         rsurface.modelvertex3f_bufferobject = 0;
9869         rsurface.modelvertex3f_bufferoffset = 0;
9870         rsurface.modelsvector3f_bufferobject = 0;
9871         rsurface.modelsvector3f_bufferoffset = 0;
9872         rsurface.modeltvector3f_bufferobject = 0;
9873         rsurface.modeltvector3f_bufferoffset = 0;
9874         rsurface.modelnormal3f_bufferobject = 0;
9875         rsurface.modelnormal3f_bufferoffset = 0;
9876         rsurface.generatedvertex = true;
9877         rsurface.modellightmapcolor4f  = color4f;
9878         rsurface.modellightmapcolor4f_bufferobject = 0;
9879         rsurface.modellightmapcolor4f_bufferoffset = 0;
9880         rsurface.modeltexcoordtexture2f  = texcoord2f;
9881         rsurface.modeltexcoordtexture2f_bufferobject = 0;
9882         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9883         rsurface.modeltexcoordlightmap2f  = NULL;
9884         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9885         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9886         rsurface.modelelement3i = element3i;
9887         rsurface.modelelement3s = element3s;
9888         rsurface.modelelement3i_bufferobject = 0;
9889         rsurface.modelelement3s_bufferobject = 0;
9890         rsurface.modellightmapoffsets = NULL;
9891         rsurface.modelsurfaces = NULL;
9892         rsurface.vertex3f  = rsurface.modelvertex3f;
9893         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9894         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9895         rsurface.svector3f = rsurface.modelsvector3f;
9896         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9897         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9898         rsurface.tvector3f = rsurface.modeltvector3f;
9899         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9900         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9901         rsurface.normal3f  = rsurface.modelnormal3f;
9902         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9903         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9904         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9905
9906         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9907         {
9908                 if ((wantnormals || wanttangents) && !normal3f)
9909                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9910                 if (wanttangents && !svector3f)
9911                         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);
9912         }
9913 }
9914
9915 float RSurf_FogPoint(const float *v)
9916 {
9917         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9918         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9919         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9920         float FogHeightFade = r_refdef.fogheightfade;
9921         float fogfrac;
9922         unsigned int fogmasktableindex;
9923         if (r_refdef.fogplaneviewabove)
9924                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9925         else
9926                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9927         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9928         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9929 }
9930
9931 float RSurf_FogVertex(const float *v)
9932 {
9933         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9934         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9935         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9936         float FogHeightFade = rsurface.fogheightfade;
9937         float fogfrac;
9938         unsigned int fogmasktableindex;
9939         if (r_refdef.fogplaneviewabove)
9940                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9941         else
9942                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9943         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9944         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9945 }
9946
9947 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9948 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9949 {
9950         int deformindex;
9951         int texturesurfaceindex;
9952         int i, j;
9953         float amplitude;
9954         float animpos;
9955         float scale;
9956         const float *v1, *in_tc;
9957         float *out_tc;
9958         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9959         float waveparms[4];
9960         q3shaderinfo_deform_t *deform;
9961         // 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
9962         if (rsurface.generatedvertex)
9963         {
9964                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9965                         generatenormals = true;
9966                 for (i = 0;i < Q3MAXDEFORMS;i++)
9967                 {
9968                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9969                         {
9970                                 generatetangents = true;
9971                                 generatenormals = true;
9972                         }
9973                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9974                                 generatenormals = true;
9975                 }
9976                 if (generatenormals && !rsurface.modelnormal3f)
9977                 {
9978                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9979                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9980                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9981                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9982                 }
9983                 if (generatetangents && !rsurface.modelsvector3f)
9984                 {
9985                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9986                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9987                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9988                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9989                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9990                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9991                         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);
9992                 }
9993         }
9994         rsurface.vertex3f  = rsurface.modelvertex3f;
9995         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9996         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9997         rsurface.svector3f = rsurface.modelsvector3f;
9998         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9999         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10000         rsurface.tvector3f = rsurface.modeltvector3f;
10001         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
10002         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10003         rsurface.normal3f  = rsurface.modelnormal3f;
10004         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
10005         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10006         // if vertices are deformed (sprite flares and things in maps, possibly
10007         // water waves, bulges and other deformations), generate them into
10008         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
10009         // (may be static model data or generated data for an animated model, or
10010         //  the previous deform pass)
10011         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10012         {
10013                 switch (deform->deform)
10014                 {
10015                 default:
10016                 case Q3DEFORM_PROJECTIONSHADOW:
10017                 case Q3DEFORM_TEXT0:
10018                 case Q3DEFORM_TEXT1:
10019                 case Q3DEFORM_TEXT2:
10020                 case Q3DEFORM_TEXT3:
10021                 case Q3DEFORM_TEXT4:
10022                 case Q3DEFORM_TEXT5:
10023                 case Q3DEFORM_TEXT6:
10024                 case Q3DEFORM_TEXT7:
10025                 case Q3DEFORM_NONE:
10026                         break;
10027                 case Q3DEFORM_AUTOSPRITE:
10028                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10029                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10030                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10031                         VectorNormalize(newforward);
10032                         VectorNormalize(newright);
10033                         VectorNormalize(newup);
10034                         // make deformed versions of only the model vertices used by the specified surfaces
10035                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10036                         {
10037                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10038                                 // a single autosprite surface can contain multiple sprites...
10039                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
10040                                 {
10041                                         VectorClear(center);
10042                                         for (i = 0;i < 4;i++)
10043                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
10044                                         VectorScale(center, 0.25f, center);
10045                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
10046                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
10047                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
10048                                         for (i = 0;i < 4;i++)
10049                                         {
10050                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
10051                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
10052                                         }
10053                                 }
10054                                 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);
10055                                 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);
10056                         }
10057                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10058                         rsurface.vertex3f_bufferobject = 0;
10059                         rsurface.vertex3f_bufferoffset = 0;
10060                         rsurface.svector3f = rsurface.array_deformedsvector3f;
10061                         rsurface.svector3f_bufferobject = 0;
10062                         rsurface.svector3f_bufferoffset = 0;
10063                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
10064                         rsurface.tvector3f_bufferobject = 0;
10065                         rsurface.tvector3f_bufferoffset = 0;
10066                         rsurface.normal3f = rsurface.array_deformednormal3f;
10067                         rsurface.normal3f_bufferobject = 0;
10068                         rsurface.normal3f_bufferoffset = 0;
10069                         break;
10070                 case Q3DEFORM_AUTOSPRITE2:
10071                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10072                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10073                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10074                         VectorNormalize(newforward);
10075                         VectorNormalize(newright);
10076                         VectorNormalize(newup);
10077                         // make deformed versions of only the model vertices used by the specified surfaces
10078                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10079                         {
10080                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10081                                 const float *v1, *v2;
10082                                 vec3_t start, end;
10083                                 float f, l;
10084                                 struct
10085                                 {
10086                                         float length2;
10087                                         const float *v1;
10088                                         const float *v2;
10089                                 }
10090                                 shortest[2];
10091                                 memset(shortest, 0, sizeof(shortest));
10092                                 // a single autosprite surface can contain multiple sprites...
10093                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
10094                                 {
10095                                         VectorClear(center);
10096                                         for (i = 0;i < 4;i++)
10097                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
10098                                         VectorScale(center, 0.25f, center);
10099                                         // find the two shortest edges, then use them to define the
10100                                         // axis vectors for rotating around the central axis
10101                                         for (i = 0;i < 6;i++)
10102                                         {
10103                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
10104                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
10105 #if 0
10106                                                 Debug_PolygonBegin(NULL, 0);
10107                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
10108                                                 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);
10109                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
10110                                                 Debug_PolygonEnd();
10111 #endif
10112                                                 l = VectorDistance2(v1, v2);
10113                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
10114                                                 if (v1[2] != v2[2])
10115                                                         l += (1.0f / 1024.0f);
10116                                                 if (shortest[0].length2 > l || i == 0)
10117                                                 {
10118                                                         shortest[1] = shortest[0];
10119                                                         shortest[0].length2 = l;
10120                                                         shortest[0].v1 = v1;
10121                                                         shortest[0].v2 = v2;
10122                                                 }
10123                                                 else if (shortest[1].length2 > l || i == 1)
10124                                                 {
10125                                                         shortest[1].length2 = l;
10126                                                         shortest[1].v1 = v1;
10127                                                         shortest[1].v2 = v2;
10128                                                 }
10129                                         }
10130                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
10131                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
10132 #if 0
10133                                         Debug_PolygonBegin(NULL, 0);
10134                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
10135                                         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);
10136                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
10137                                         Debug_PolygonEnd();
10138 #endif
10139                                         // this calculates the right vector from the shortest edge
10140                                         // and the up vector from the edge midpoints
10141                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
10142                                         VectorNormalize(right);
10143                                         VectorSubtract(end, start, up);
10144                                         VectorNormalize(up);
10145                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10146                                         VectorSubtract(rsurface.localvieworigin, center, forward);
10147                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10148                                         VectorNegate(forward, forward);
10149                                         VectorReflect(forward, 0, up, forward);
10150                                         VectorNormalize(forward);
10151                                         CrossProduct(up, forward, newright);
10152                                         VectorNormalize(newright);
10153 #if 0
10154                                         Debug_PolygonBegin(NULL, 0);
10155                                         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);
10156                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
10157                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
10158                                         Debug_PolygonEnd();
10159 #endif
10160 #if 0
10161                                         Debug_PolygonBegin(NULL, 0);
10162                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
10163                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
10164                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
10165                                         Debug_PolygonEnd();
10166 #endif
10167                                         // rotate the quad around the up axis vector, this is made
10168                                         // especially easy by the fact we know the quad is flat,
10169                                         // so we only have to subtract the center position and
10170                                         // measure distance along the right vector, and then
10171                                         // multiply that by the newright vector and add back the
10172                                         // center position
10173                                         // we also need to subtract the old position to undo the
10174                                         // displacement from the center, which we do with a
10175                                         // DotProduct, the subtraction/addition of center is also
10176                                         // optimized into DotProducts here
10177                                         l = DotProduct(right, center);
10178                                         for (i = 0;i < 4;i++)
10179                                         {
10180                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
10181                                                 f = DotProduct(right, v1) - l;
10182                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
10183                                         }
10184                                 }
10185                                 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);
10186                                 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);
10187                         }
10188                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10189                         rsurface.vertex3f_bufferobject = 0;
10190                         rsurface.vertex3f_bufferoffset = 0;
10191                         rsurface.svector3f = rsurface.array_deformedsvector3f;
10192                         rsurface.svector3f_bufferobject = 0;
10193                         rsurface.svector3f_bufferoffset = 0;
10194                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
10195                         rsurface.tvector3f_bufferobject = 0;
10196                         rsurface.tvector3f_bufferoffset = 0;
10197                         rsurface.normal3f = rsurface.array_deformednormal3f;
10198                         rsurface.normal3f_bufferobject = 0;
10199                         rsurface.normal3f_bufferoffset = 0;
10200                         break;
10201                 case Q3DEFORM_NORMAL:
10202                         // deform the normals to make reflections wavey
10203                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10204                         {
10205                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10206                                 for (j = 0;j < surface->num_vertices;j++)
10207                                 {
10208                                         float vertex[3];
10209                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
10210                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
10211                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
10212                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10213                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10214                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10215                                         VectorNormalize(normal);
10216                                 }
10217                                 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);
10218                         }
10219                         rsurface.svector3f = rsurface.array_deformedsvector3f;
10220                         rsurface.svector3f_bufferobject = 0;
10221                         rsurface.svector3f_bufferoffset = 0;
10222                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
10223                         rsurface.tvector3f_bufferobject = 0;
10224                         rsurface.tvector3f_bufferoffset = 0;
10225                         rsurface.normal3f = rsurface.array_deformednormal3f;
10226                         rsurface.normal3f_bufferobject = 0;
10227                         rsurface.normal3f_bufferoffset = 0;
10228                         break;
10229                 case Q3DEFORM_WAVE:
10230                         // deform vertex array to make wavey water and flags and such
10231                         waveparms[0] = deform->waveparms[0];
10232                         waveparms[1] = deform->waveparms[1];
10233                         waveparms[2] = deform->waveparms[2];
10234                         waveparms[3] = deform->waveparms[3];
10235                         // this is how a divisor of vertex influence on deformation
10236                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10237                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10238                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10239                         {
10240                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10241                                 for (j = 0;j < surface->num_vertices;j++)
10242                                 {
10243                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
10244                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
10245                                         // if the wavefunc depends on time, evaluate it per-vertex
10246                                         if (waveparms[3])
10247                                         {
10248                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
10249                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10250                                         }
10251                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
10252                                 }
10253                         }
10254                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10255                         rsurface.vertex3f_bufferobject = 0;
10256                         rsurface.vertex3f_bufferoffset = 0;
10257                         break;
10258                 case Q3DEFORM_BULGE:
10259                         // deform vertex array to make the surface have moving bulges
10260                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10261                         {
10262                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10263                                 for (j = 0;j < surface->num_vertices;j++)
10264                                 {
10265                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
10266                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
10267                                 }
10268                         }
10269                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10270                         rsurface.vertex3f_bufferobject = 0;
10271                         rsurface.vertex3f_bufferoffset = 0;
10272                         break;
10273                 case Q3DEFORM_MOVE:
10274                         // deform vertex array
10275                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10276                         VectorScale(deform->parms, scale, waveparms);
10277                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10278                         {
10279                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10280                                 for (j = 0;j < surface->num_vertices;j++)
10281                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
10282                         }
10283                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10284                         rsurface.vertex3f_bufferobject = 0;
10285                         rsurface.vertex3f_bufferoffset = 0;
10286                         break;
10287                 }
10288         }
10289         // generate texcoords based on the chosen texcoord source
10290         switch(rsurface.texture->tcgen.tcgen)
10291         {
10292         default:
10293         case Q3TCGEN_TEXTURE:
10294                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
10295                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
10296                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
10297                 break;
10298         case Q3TCGEN_LIGHTMAP:
10299                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
10300                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
10301                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
10302                 break;
10303         case Q3TCGEN_VECTOR:
10304                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10305                 {
10306                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10307                         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)
10308                         {
10309                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
10310                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
10311                         }
10312                 }
10313                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10314                 rsurface.texcoordtexture2f_bufferobject  = 0;
10315                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10316                 break;
10317         case Q3TCGEN_ENVIRONMENT:
10318                 // make environment reflections using a spheremap
10319                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10320                 {
10321                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10322                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
10323                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
10324                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
10325                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
10326                         {
10327                                 // identical to Q3A's method, but executed in worldspace so
10328                                 // carried models can be shiny too
10329
10330                                 float viewer[3], d, reflected[3], worldreflected[3];
10331
10332                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
10333                                 // VectorNormalize(viewer);
10334
10335                                 d = DotProduct(normal, viewer);
10336
10337                                 reflected[0] = normal[0]*2*d - viewer[0];
10338                                 reflected[1] = normal[1]*2*d - viewer[1];
10339                                 reflected[2] = normal[2]*2*d - viewer[2];
10340                                 // note: this is proportinal to viewer, so we can normalize later
10341
10342                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10343                                 VectorNormalize(worldreflected);
10344
10345                                 // note: this sphere map only uses world x and z!
10346                                 // so positive and negative y will LOOK THE SAME.
10347                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
10348                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
10349                         }
10350                 }
10351                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10352                 rsurface.texcoordtexture2f_bufferobject  = 0;
10353                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10354                 break;
10355         }
10356         // the only tcmod that needs software vertex processing is turbulent, so
10357         // check for it here and apply the changes if needed
10358         // and we only support that as the first one
10359         // (handling a mixture of turbulent and other tcmods would be problematic
10360         //  without punting it entirely to a software path)
10361         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10362         {
10363                 amplitude = rsurface.texture->tcmods[0].parms[1];
10364                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
10365                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10366                 {
10367                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10368                         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)
10369                         {
10370                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10371                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10372                         }
10373                 }
10374                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10375                 rsurface.texcoordtexture2f_bufferobject  = 0;
10376                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10377         }
10378         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
10379         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
10380         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10381         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
10382 }
10383
10384 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10385 {
10386         int i, j;
10387         const msurface_t *surface = texturesurfacelist[0];
10388         const msurface_t *surface2;
10389         int firstvertex;
10390         int endvertex;
10391         int numvertices;
10392         int numtriangles;
10393         // TODO: lock all array ranges before render, rather than on each surface
10394         if (texturenumsurfaces == 1)
10395                 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);
10396         else if (r_batchmode.integer == 2)
10397         {
10398                 #define MAXBATCHTRIANGLES 65536
10399                 int batchtriangles = 0;
10400                 static int batchelements[MAXBATCHTRIANGLES*3];
10401                 for (i = 0;i < texturenumsurfaces;i = j)
10402                 {
10403                         surface = texturesurfacelist[i];
10404                         j = i + 1;
10405                         if (surface->num_triangles > MAXBATCHTRIANGLES)
10406                         {
10407                                 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);
10408                                 continue;
10409                         }
10410                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10411                         batchtriangles = surface->num_triangles;
10412                         firstvertex = surface->num_firstvertex;
10413                         endvertex = surface->num_firstvertex + surface->num_vertices;
10414                         for (;j < texturenumsurfaces;j++)
10415                         {
10416                                 surface2 = texturesurfacelist[j];
10417                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10418                                         break;
10419                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10420                                 batchtriangles += surface2->num_triangles;
10421                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
10422                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10423                         }
10424                         surface2 = texturesurfacelist[j-1];
10425                         numvertices = endvertex - firstvertex;
10426                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10427                 }
10428         }
10429         else if (r_batchmode.integer == 1)
10430         {
10431                 for (i = 0;i < texturenumsurfaces;i = j)
10432                 {
10433                         surface = texturesurfacelist[i];
10434                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10435                                 if (texturesurfacelist[j] != surface2)
10436                                         break;
10437                         surface2 = texturesurfacelist[j-1];
10438                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10439                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10440                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10441                 }
10442         }
10443         else
10444         {
10445                 for (i = 0;i < texturenumsurfaces;i++)
10446                 {
10447                         surface = texturesurfacelist[i];
10448                         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);
10449                 }
10450         }
10451 }
10452
10453 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
10454 {
10455         switch(vid.renderpath)
10456         {
10457         case RENDERPATH_CGGL:
10458 #ifdef SUPPORTCG
10459                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
10460                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
10461 #endif
10462                 break;
10463         case RENDERPATH_GL20:
10464                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
10465                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
10466                 break;
10467         case RENDERPATH_GL13:
10468         case RENDERPATH_GL11:
10469                 R_Mesh_TexBind(0, surface->lightmaptexture);
10470                 break;
10471         }
10472 }
10473
10474 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
10475 {
10476         // pick the closest matching water plane and bind textures
10477         int planeindex, vertexindex;
10478         float d, bestd;
10479         vec3_t vert;
10480         const float *v;
10481         r_waterstate_waterplane_t *p, *bestp;
10482         bestd = 0;
10483         bestp = NULL;
10484         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10485         {
10486                 if(p->camera_entity != rsurface.texture->camera_entity)
10487                         continue;
10488                 d = 0;
10489                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
10490                 {
10491                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10492                         d += fabs(PlaneDiff(vert, &p->plane));
10493                 }
10494                 if (bestd > d || !bestp)
10495                 {
10496                         bestd = d;
10497                         bestp = p;
10498                 }
10499         }
10500         switch(vid.renderpath)
10501         {
10502         case RENDERPATH_CGGL:
10503 #ifdef SUPPORTCG
10504                 if (r_cg_permutation->fp_Texture_Refraction) {CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR}
10505                 else if (r_cg_permutation->fp_Texture_First) {CG_BindTexture(r_cg_permutation->fp_Texture_First, bestp ? bestp->texture_camera : r_texture_black);CHECKCGERROR}
10506                 if (r_cg_permutation->fp_Texture_Reflection) {CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR}
10507 #endif
10508                 break;
10509         case RENDERPATH_GL20:
10510                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
10511                 else if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST, bestp ? bestp->texture_camera : r_texture_black);
10512                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
10513                 break;
10514         case RENDERPATH_GL13:
10515         case RENDERPATH_GL11:
10516                 break;
10517         }
10518 }
10519
10520 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10521 {
10522         int i;
10523         const msurface_t *surface;
10524         if (r_waterstate.renderingscene)
10525                 return;
10526         for (i = 0;i < texturenumsurfaces;i++)
10527         {
10528                 surface = texturesurfacelist[i];
10529                 RSurf_BindLightmapForSurface(surface);
10530                 RSurf_BindReflectionForSurface(surface);
10531                 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);
10532         }
10533 }
10534
10535 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10536 {
10537         int i;
10538         int j;
10539         const msurface_t *surface = texturesurfacelist[0];
10540         const msurface_t *surface2;
10541         int firstvertex;
10542         int endvertex;
10543         int numvertices;
10544         int numtriangles;
10545         if (texturenumsurfaces == 1)
10546         {
10547                 RSurf_BindLightmapForSurface(surface);
10548                 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);
10549         }
10550         else if (r_batchmode.integer == 2)
10551         {
10552                 int batchtriangles = 0;
10553                 static int batchelements[MAXBATCHTRIANGLES*3];
10554                 for (i = 0;i < texturenumsurfaces;i = j)
10555                 {
10556                         surface = texturesurfacelist[i];
10557                         RSurf_BindLightmapForSurface(surface);
10558                         j = i + 1;
10559                         if (surface->num_triangles > MAXBATCHTRIANGLES)
10560                         {
10561                                 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);
10562                                 continue;
10563                         }
10564                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10565                         batchtriangles = surface->num_triangles;
10566                         firstvertex = surface->num_firstvertex;
10567                         endvertex = surface->num_firstvertex + surface->num_vertices;
10568                         for (;j < texturenumsurfaces;j++)
10569                         {
10570                                 surface2 = texturesurfacelist[j];
10571                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10572                                         break;
10573                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10574                                 batchtriangles += surface2->num_triangles;
10575                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
10576                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10577                         }
10578                         surface2 = texturesurfacelist[j-1];
10579                         numvertices = endvertex - firstvertex;
10580                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10581                 }
10582         }
10583         else if (r_batchmode.integer == 1)
10584         {
10585 #if 0
10586                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
10587                 for (i = 0;i < texturenumsurfaces;i = j)
10588                 {
10589                         surface = texturesurfacelist[i];
10590                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10591                                 if (texturesurfacelist[j] != surface2)
10592                                         break;
10593                         Con_Printf(" %i", j - i);
10594                 }
10595                 Con_Printf("\n");
10596                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
10597 #endif
10598                 for (i = 0;i < texturenumsurfaces;i = j)
10599                 {
10600                         surface = texturesurfacelist[i];
10601                         RSurf_BindLightmapForSurface(surface);
10602                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10603                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
10604                                         break;
10605 #if 0
10606                         Con_Printf(" %i", j - i);
10607 #endif
10608                         surface2 = texturesurfacelist[j-1];
10609                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10610                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10611                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10612                 }
10613 #if 0
10614                 Con_Printf("\n");
10615 #endif
10616         }
10617         else
10618         {
10619                 for (i = 0;i < texturenumsurfaces;i++)
10620                 {
10621                         surface = texturesurfacelist[i];
10622                         RSurf_BindLightmapForSurface(surface);
10623                         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);
10624                 }
10625         }
10626 }
10627
10628 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10629 {
10630         int j;
10631         int texturesurfaceindex;
10632         if (r_showsurfaces.integer == 2)
10633         {
10634                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10635                 {
10636                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10637                         for (j = 0;j < surface->num_triangles;j++)
10638                         {
10639                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
10640                                 GL_Color(f, f, f, 1);
10641                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10642                         }
10643                 }
10644         }
10645         else
10646         {
10647                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10648                 {
10649                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10650                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
10651                         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);
10652                         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);
10653                 }
10654         }
10655 }
10656
10657 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10658 {
10659         int texturesurfaceindex;
10660         int i;
10661         const float *v;
10662         float *c2;
10663         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10664         {
10665                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10666                 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)
10667                 {
10668                         c2[0] = 0.5;
10669                         c2[1] = 0.5;
10670                         c2[2] = 0.5;
10671                         c2[3] = 1;
10672                 }
10673         }
10674         rsurface.lightmapcolor4f = rsurface.array_color4f;
10675         rsurface.lightmapcolor4f_bufferobject = 0;
10676         rsurface.lightmapcolor4f_bufferoffset = 0;
10677 }
10678
10679 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10680 {
10681         int texturesurfaceindex;
10682         int i;
10683         float f;
10684         const float *v;
10685         const float *c;
10686         float *c2;
10687         if (rsurface.lightmapcolor4f)
10688         {
10689                 // generate color arrays for the surfaces in this list
10690                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10691                 {
10692                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10693                         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)
10694                         {
10695                                 f = RSurf_FogVertex(v);
10696                                 c2[0] = c[0] * f;
10697                                 c2[1] = c[1] * f;
10698                                 c2[2] = c[2] * f;
10699                                 c2[3] = c[3];
10700                         }
10701                 }
10702         }
10703         else
10704         {
10705                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10706                 {
10707                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10708                         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)
10709                         {
10710                                 f = RSurf_FogVertex(v);
10711                                 c2[0] = f;
10712                                 c2[1] = f;
10713                                 c2[2] = f;
10714                                 c2[3] = 1;
10715                         }
10716                 }
10717         }
10718         rsurface.lightmapcolor4f = rsurface.array_color4f;
10719         rsurface.lightmapcolor4f_bufferobject = 0;
10720         rsurface.lightmapcolor4f_bufferoffset = 0;
10721 }
10722
10723 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10724 {
10725         int texturesurfaceindex;
10726         int i;
10727         float f;
10728         const float *v;
10729         const float *c;
10730         float *c2;
10731         if (!rsurface.lightmapcolor4f)
10732                 return;
10733         // generate color arrays for the surfaces in this list
10734         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10735         {
10736                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10737                 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)
10738                 {
10739                         f = RSurf_FogVertex(v);
10740                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10741                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10742                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10743                         c2[3] = c[3];
10744                 }
10745         }
10746         rsurface.lightmapcolor4f = rsurface.array_color4f;
10747         rsurface.lightmapcolor4f_bufferobject = 0;
10748         rsurface.lightmapcolor4f_bufferoffset = 0;
10749 }
10750
10751 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10752 {
10753         int texturesurfaceindex;
10754         int i;
10755         const float *c;
10756         float *c2;
10757         if (!rsurface.lightmapcolor4f)
10758                 return;
10759         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10760         {
10761                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10762                 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)
10763                 {
10764                         c2[0] = c[0] * r;
10765                         c2[1] = c[1] * g;
10766                         c2[2] = c[2] * b;
10767                         c2[3] = c[3] * a;
10768                 }
10769         }
10770         rsurface.lightmapcolor4f = rsurface.array_color4f;
10771         rsurface.lightmapcolor4f_bufferobject = 0;
10772         rsurface.lightmapcolor4f_bufferoffset = 0;
10773 }
10774
10775 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10776 {
10777         int texturesurfaceindex;
10778         int i;
10779         const float *c;
10780         float *c2;
10781         if (!rsurface.lightmapcolor4f)
10782                 return;
10783         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10784         {
10785                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10786                 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)
10787                 {
10788                         c2[0] = c[0] + r_refdef.scene.ambient;
10789                         c2[1] = c[1] + r_refdef.scene.ambient;
10790                         c2[2] = c[2] + r_refdef.scene.ambient;
10791                         c2[3] = c[3];
10792                 }
10793         }
10794         rsurface.lightmapcolor4f = rsurface.array_color4f;
10795         rsurface.lightmapcolor4f_bufferobject = 0;
10796         rsurface.lightmapcolor4f_bufferoffset = 0;
10797 }
10798
10799 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10800 {
10801         // TODO: optimize
10802         rsurface.lightmapcolor4f = NULL;
10803         rsurface.lightmapcolor4f_bufferobject = 0;
10804         rsurface.lightmapcolor4f_bufferoffset = 0;
10805         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10806         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10807         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10808         GL_Color(r, g, b, a);
10809         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10810 }
10811
10812 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10813 {
10814         // TODO: optimize applyfog && applycolor case
10815         // just apply fog if necessary, and tint the fog color array if necessary
10816         rsurface.lightmapcolor4f = NULL;
10817         rsurface.lightmapcolor4f_bufferobject = 0;
10818         rsurface.lightmapcolor4f_bufferoffset = 0;
10819         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10820         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10821         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10822         GL_Color(r, g, b, a);
10823         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10824 }
10825
10826 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10827 {
10828         int texturesurfaceindex;
10829         int i;
10830         float *c;
10831         // TODO: optimize
10832         if (texturesurfacelist[0]->lightmapinfo)
10833         {
10834                 // generate color arrays for the surfaces in this list
10835                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10836                 {
10837                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10838                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10839                         {
10840                                 if (surface->lightmapinfo->samples)
10841                                 {
10842                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10843                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10844                                         VectorScale(lm, scale, c);
10845                                         if (surface->lightmapinfo->styles[1] != 255)
10846                                         {
10847                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10848                                                 lm += size3;
10849                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10850                                                 VectorMA(c, scale, lm, c);
10851                                                 if (surface->lightmapinfo->styles[2] != 255)
10852                                                 {
10853                                                         lm += size3;
10854                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10855                                                         VectorMA(c, scale, lm, c);
10856                                                         if (surface->lightmapinfo->styles[3] != 255)
10857                                                         {
10858                                                                 lm += size3;
10859                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10860                                                                 VectorMA(c, scale, lm, c);
10861                                                         }
10862                                                 }
10863                                         }
10864                                 }
10865                                 else
10866                                         VectorClear(c);
10867                                 c[3] = 1;
10868                         }
10869                 }
10870                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10871                 rsurface.lightmapcolor4f_bufferobject = 0;
10872                 rsurface.lightmapcolor4f_bufferoffset = 0;
10873         }
10874         else
10875         {
10876                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10877                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10878                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10879         }
10880         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10881         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10882         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10883         GL_Color(r, g, b, a);
10884         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10885 }
10886
10887 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10888 {
10889         int texturesurfaceindex;
10890         int i;
10891         float f;
10892         float alpha;
10893         const float *v;
10894         const float *n;
10895         float *c;
10896         vec3_t ambientcolor;
10897         vec3_t diffusecolor;
10898         vec3_t lightdir;
10899         // TODO: optimize
10900         // model lighting
10901         VectorCopy(rsurface.modellight_lightdir, lightdir);
10902         f = 0.5f * r_refdef.lightmapintensity;
10903         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10904         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10905         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10906         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10907         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10908         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10909         alpha = *a;
10910         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10911         {
10912                 // generate color arrays for the surfaces in this list
10913                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10914                 {
10915                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10916                         int numverts = surface->num_vertices;
10917                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10918                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
10919                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10920                         // q3-style directional shading
10921                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10922                         {
10923                                 if ((f = DotProduct(n, lightdir)) > 0)
10924                                         VectorMA(ambientcolor, f, diffusecolor, c);
10925                                 else
10926                                         VectorCopy(ambientcolor, c);
10927                                 c[3] = alpha;
10928                         }
10929                 }
10930                 *r = 1;
10931                 *g = 1;
10932                 *b = 1;
10933                 *a = 1;
10934                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10935                 rsurface.lightmapcolor4f_bufferobject = 0;
10936                 rsurface.lightmapcolor4f_bufferoffset = 0;
10937                 *applycolor = false;
10938         }
10939         else
10940         {
10941                 *r = ambientcolor[0];
10942                 *g = ambientcolor[1];
10943                 *b = ambientcolor[2];
10944                 rsurface.lightmapcolor4f = NULL;
10945                 rsurface.lightmapcolor4f_bufferobject = 0;
10946                 rsurface.lightmapcolor4f_bufferoffset = 0;
10947         }
10948 }
10949
10950 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10951 {
10952         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10953         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10954         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10955         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10956         GL_Color(r, g, b, a);
10957         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10958 }
10959
10960 void RSurf_SetupDepthAndCulling(void)
10961 {
10962         // submodels are biased to avoid z-fighting with world surfaces that they
10963         // may be exactly overlapping (avoids z-fighting artifacts on certain
10964         // doors and things in Quake maps)
10965         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10966         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10967         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10968         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10969 }
10970
10971 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10972 {
10973         // transparent sky would be ridiculous
10974         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10975                 return;
10976         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10977         skyrenderlater = true;
10978         RSurf_SetupDepthAndCulling();
10979         GL_DepthMask(true);
10980         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10981         // skymasking on them, and Quake3 never did sky masking (unlike
10982         // software Quake and software Quake2), so disable the sky masking
10983         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10984         // and skymasking also looks very bad when noclipping outside the
10985         // level, so don't use it then either.
10986         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10987         {
10988                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10989                 R_Mesh_ColorPointer(NULL, 0, 0);
10990                 R_Mesh_ResetTextureState();
10991                 if (skyrendermasked)
10992                 {
10993                         R_SetupShader_DepthOrShadow();
10994                         // depth-only (masking)
10995                         GL_ColorMask(0,0,0,0);
10996                         // just to make sure that braindead drivers don't draw
10997                         // anything despite that colormask...
10998                         GL_BlendFunc(GL_ZERO, GL_ONE);
10999                 }
11000                 else
11001                 {
11002                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11003                         // fog sky
11004                         GL_BlendFunc(GL_ONE, GL_ZERO);
11005                 }
11006                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11007                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11008                 if (skyrendermasked)
11009                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11010         }
11011         R_Mesh_ResetTextureState();
11012         GL_Color(1, 1, 1, 1);
11013 }
11014
11015 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
11016 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
11017 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11018 {
11019         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
11020                 return;
11021         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
11022         if (prepass)
11023         {
11024                 // render screenspace normalmap to texture
11025                 GL_DepthMask(true);
11026                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
11027                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11028         }
11029         else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
11030         {
11031                 // render water or distortion background, then blend surface on top
11032                 GL_DepthMask(true);
11033                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
11034                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
11035                 GL_DepthMask(false);
11036                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
11037                 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
11038                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
11039                 else
11040                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11041         }
11042         else
11043         {
11044                 // render surface normally
11045                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
11046                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
11047                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
11048                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
11049                 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
11050                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
11051                 else
11052                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11053         }
11054 }
11055
11056 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11057 {
11058         // OpenGL 1.3 path - anything not completely ancient
11059         int texturesurfaceindex;
11060         qboolean applycolor;
11061         qboolean applyfog;
11062         int layerindex;
11063         const texturelayer_t *layer;
11064         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11065
11066         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11067         {
11068                 vec4_t layercolor;
11069                 int layertexrgbscale;
11070                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11071                 {
11072                         if (layerindex == 0)
11073                                 GL_AlphaTest(true);
11074                         else
11075                         {
11076                                 GL_AlphaTest(false);
11077                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
11078                         }
11079                 }
11080                 GL_DepthMask(layer->depthmask && writedepth);
11081                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11082                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
11083                 {
11084                         layertexrgbscale = 4;
11085                         VectorScale(layer->color, 0.25f, layercolor);
11086                 }
11087                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
11088                 {
11089                         layertexrgbscale = 2;
11090                         VectorScale(layer->color, 0.5f, layercolor);
11091                 }
11092                 else
11093                 {
11094                         layertexrgbscale = 1;
11095                         VectorScale(layer->color, 1.0f, layercolor);
11096                 }
11097                 layercolor[3] = layer->color[3];
11098                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
11099                 R_Mesh_ColorPointer(NULL, 0, 0);
11100                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11101                 switch (layer->type)
11102                 {
11103                 case TEXTURELAYERTYPE_LITTEXTURE:
11104                         // single-pass lightmapped texture with 2x rgbscale
11105                         R_Mesh_TexBind(0, r_texture_white);
11106                         R_Mesh_TexMatrix(0, NULL);
11107                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11108                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
11109                         R_Mesh_TexBind(1, layer->texture);
11110                         R_Mesh_TexMatrix(1, &layer->texmatrix);
11111                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11112                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11113                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11114                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11115                         else if (rsurface.uselightmaptexture)
11116                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11117                         else
11118                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11119                         break;
11120                 case TEXTURELAYERTYPE_TEXTURE:
11121                         // singletexture unlit texture with transparency support
11122                         R_Mesh_TexBind(0, layer->texture);
11123                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11124                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11125                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11126                         R_Mesh_TexBind(1, 0);
11127                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
11128                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11129                         break;
11130                 case TEXTURELAYERTYPE_FOG:
11131                         // singletexture fogging
11132                         if (layer->texture)
11133                         {
11134                                 R_Mesh_TexBind(0, layer->texture);
11135                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11136                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11137                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11138                         }
11139                         else
11140                         {
11141                                 R_Mesh_TexBind(0, 0);
11142                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
11143                         }
11144                         R_Mesh_TexBind(1, 0);
11145                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
11146                         // generate a color array for the fog pass
11147                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
11148                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11149                         {
11150                                 int i;
11151                                 float f;
11152                                 const float *v;
11153                                 float *c;
11154                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11155                                 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)
11156                                 {
11157                                         f = 1 - RSurf_FogVertex(v);
11158                                         c[0] = layercolor[0];
11159                                         c[1] = layercolor[1];
11160                                         c[2] = layercolor[2];
11161                                         c[3] = f * layercolor[3];
11162                                 }
11163                         }
11164                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11165                         break;
11166                 default:
11167                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11168                 }
11169         }
11170         CHECKGLERROR
11171         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11172         {
11173                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11174                 GL_AlphaTest(false);
11175         }
11176 }
11177
11178 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11179 {
11180         // OpenGL 1.1 - crusty old voodoo path
11181         int texturesurfaceindex;
11182         qboolean applyfog;
11183         int layerindex;
11184         const texturelayer_t *layer;
11185         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11186
11187         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11188         {
11189                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11190                 {
11191                         if (layerindex == 0)
11192                                 GL_AlphaTest(true);
11193                         else
11194                         {
11195                                 GL_AlphaTest(false);
11196                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
11197                         }
11198                 }
11199                 GL_DepthMask(layer->depthmask && writedepth);
11200                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11201                 R_Mesh_ColorPointer(NULL, 0, 0);
11202                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11203                 switch (layer->type)
11204                 {
11205                 case TEXTURELAYERTYPE_LITTEXTURE:
11206                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
11207                         {
11208                                 // two-pass lit texture with 2x rgbscale
11209                                 // first the lightmap pass
11210                                 R_Mesh_TexBind(0, r_texture_white);
11211                                 R_Mesh_TexMatrix(0, NULL);
11212                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11213                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
11214                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11215                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11216                                 else if (rsurface.uselightmaptexture)
11217                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11218                                 else
11219                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
11220                                 // then apply the texture to it
11221                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
11222                                 R_Mesh_TexBind(0, layer->texture);
11223                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11224                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11225                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11226                                 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);
11227                         }
11228                         else
11229                         {
11230                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
11231                                 R_Mesh_TexBind(0, layer->texture);
11232                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11233                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11234                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11235                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11236                                         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);
11237                                 else
11238                                         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);
11239                         }
11240                         break;
11241                 case TEXTURELAYERTYPE_TEXTURE:
11242                         // singletexture unlit texture with transparency support
11243                         R_Mesh_TexBind(0, layer->texture);
11244                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11245                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11246                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11247                         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);
11248                         break;
11249                 case TEXTURELAYERTYPE_FOG:
11250                         // singletexture fogging
11251                         if (layer->texture)
11252                         {
11253                                 R_Mesh_TexBind(0, layer->texture);
11254                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11255                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11256                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11257                         }
11258                         else
11259                         {
11260                                 R_Mesh_TexBind(0, 0);
11261                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
11262                         }
11263                         // generate a color array for the fog pass
11264                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
11265                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11266                         {
11267                                 int i;
11268                                 float f;
11269                                 const float *v;
11270                                 float *c;
11271                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11272                                 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)
11273                                 {
11274                                         f = 1 - RSurf_FogVertex(v);
11275                                         c[0] = layer->color[0];
11276                                         c[1] = layer->color[1];
11277                                         c[2] = layer->color[2];
11278                                         c[3] = f * layer->color[3];
11279                                 }
11280                         }
11281                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11282                         break;
11283                 default:
11284                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11285                 }
11286         }
11287         CHECKGLERROR
11288         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11289         {
11290                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11291                 GL_AlphaTest(false);
11292         }
11293 }
11294
11295 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11296 {
11297         float c[4];
11298
11299         GL_AlphaTest(false);
11300         R_Mesh_ColorPointer(NULL, 0, 0);
11301         R_Mesh_ResetTextureState();
11302         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11303
11304         if(rsurface.texture && rsurface.texture->currentskinframe)
11305         {
11306                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11307                 c[3] *= rsurface.texture->currentalpha;
11308         }
11309         else
11310         {
11311                 c[0] = 1;
11312                 c[1] = 0;
11313                 c[2] = 1;
11314                 c[3] = 1;
11315         }
11316
11317         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11318         {
11319                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11320                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11321                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11322         }
11323
11324         // brighten it up (as texture value 127 means "unlit")
11325         c[0] *= 2 * r_refdef.view.colorscale;
11326         c[1] *= 2 * r_refdef.view.colorscale;
11327         c[2] *= 2 * r_refdef.view.colorscale;
11328
11329         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11330                 c[3] *= r_wateralpha.value;
11331
11332         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11333         {
11334                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11335                 GL_DepthMask(false);
11336         }
11337         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11338         {
11339                 GL_BlendFunc(GL_ONE, GL_ONE);
11340                 GL_DepthMask(false);
11341         }
11342         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11343         {
11344                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11345                 GL_DepthMask(false);
11346         }
11347         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11348         {
11349                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11350                 GL_DepthMask(false);
11351         }
11352         else
11353         {
11354                 GL_BlendFunc(GL_ONE, GL_ZERO);
11355                 GL_DepthMask(writedepth);
11356         }
11357
11358         rsurface.lightmapcolor4f = NULL;
11359
11360         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11361         {
11362                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11363
11364                 rsurface.lightmapcolor4f = NULL;
11365                 rsurface.lightmapcolor4f_bufferobject = 0;
11366                 rsurface.lightmapcolor4f_bufferoffset = 0;
11367         }
11368         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11369         {
11370                 qboolean applycolor = true;
11371                 float one = 1.0;
11372
11373                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11374
11375                 r_refdef.lightmapintensity = 1;
11376                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
11377                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11378         }
11379         else
11380         {
11381                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11382
11383                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
11384                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
11385                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11386         }
11387
11388         if(!rsurface.lightmapcolor4f)
11389                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
11390
11391         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
11392         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
11393         if(r_refdef.fogenabled)
11394                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
11395
11396         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11397         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11398 }
11399
11400 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11401 {
11402         CHECKGLERROR
11403         RSurf_SetupDepthAndCulling();
11404         if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11405         {
11406                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11407                 return;
11408         }
11409         switch (vid.renderpath)
11410         {
11411         case RENDERPATH_GL20:
11412         case RENDERPATH_CGGL:
11413                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11414                 break;
11415         case RENDERPATH_GL13:
11416                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11417                 break;
11418         case RENDERPATH_GL11:
11419                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11420                 break;
11421         }
11422         CHECKGLERROR
11423 }
11424
11425 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11426 {
11427         CHECKGLERROR
11428         RSurf_SetupDepthAndCulling();
11429         if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11430         {
11431                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11432                 return;
11433         }
11434         switch (vid.renderpath)
11435         {
11436         case RENDERPATH_GL20:
11437         case RENDERPATH_CGGL:
11438                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11439                 break;
11440         case RENDERPATH_GL13:
11441                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11442                 break;
11443         case RENDERPATH_GL11:
11444                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11445                 break;
11446         }
11447         CHECKGLERROR
11448 }
11449
11450 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11451 {
11452         int i, j;
11453         int texturenumsurfaces, endsurface;
11454         texture_t *texture;
11455         const msurface_t *surface;
11456 #define MAXBATCH_TRANSPARENTSURFACES 256
11457         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
11458
11459         // if the model is static it doesn't matter what value we give for
11460         // wantnormals and wanttangents, so this logic uses only rules applicable
11461         // to a model, knowing that they are meaningless otherwise
11462         if (ent == r_refdef.scene.worldentity)
11463                 RSurf_ActiveWorldEntity();
11464         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11465                 RSurf_ActiveModelEntity(ent, false, false, false);
11466         else
11467         {
11468                 switch (vid.renderpath)
11469                 {
11470                 case RENDERPATH_GL20:
11471                 case RENDERPATH_CGGL:
11472                         RSurf_ActiveModelEntity(ent, true, true, false);
11473                         break;
11474                 case RENDERPATH_GL13:
11475                 case RENDERPATH_GL11:
11476                         RSurf_ActiveModelEntity(ent, true, false, false);
11477                         break;
11478                 }
11479         }
11480
11481         if (r_transparentdepthmasking.integer)
11482         {
11483                 qboolean setup = false;
11484                 for (i = 0;i < numsurfaces;i = j)
11485                 {
11486                         j = i + 1;
11487                         surface = rsurface.modelsurfaces + surfacelist[i];
11488                         texture = surface->texture;
11489                         rsurface.texture = R_GetCurrentTexture(texture);
11490                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11491                         // scan ahead until we find a different texture
11492                         endsurface = min(i + 1024, numsurfaces);
11493                         texturenumsurfaces = 0;
11494                         texturesurfacelist[texturenumsurfaces++] = surface;
11495                         for (;j < endsurface;j++)
11496                         {
11497                                 surface = rsurface.modelsurfaces + surfacelist[j];
11498                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11499                                         break;
11500                                 texturesurfacelist[texturenumsurfaces++] = surface;
11501                         }
11502                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11503                                 continue;
11504                         // render the range of surfaces as depth
11505                         if (!setup)
11506                         {
11507                                 setup = true;
11508                                 GL_ColorMask(0,0,0,0);
11509                                 GL_Color(1,1,1,1);
11510                                 GL_DepthTest(true);
11511                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11512                                 GL_DepthMask(true);
11513                                 GL_AlphaTest(false);
11514                                 R_Mesh_ColorPointer(NULL, 0, 0);
11515                                 R_Mesh_ResetTextureState();
11516                                 R_SetupShader_DepthOrShadow();
11517                         }
11518                         RSurf_SetupDepthAndCulling();
11519                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11520                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11521                 }
11522                 if (setup)
11523                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11524         }
11525
11526         for (i = 0;i < numsurfaces;i = j)
11527         {
11528                 j = i + 1;
11529                 surface = rsurface.modelsurfaces + surfacelist[i];
11530                 texture = surface->texture;
11531                 rsurface.texture = R_GetCurrentTexture(texture);
11532                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11533                 // scan ahead until we find a different texture
11534                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
11535                 texturenumsurfaces = 0;
11536                 texturesurfacelist[texturenumsurfaces++] = surface;
11537                 for (;j < endsurface;j++)
11538                 {
11539                         surface = rsurface.modelsurfaces + surfacelist[j];
11540                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11541                                 break;
11542                         texturesurfacelist[texturenumsurfaces++] = surface;
11543                 }
11544                 // render the range of surfaces
11545                 if (ent == r_refdef.scene.worldentity)
11546                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11547                 else
11548                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11549         }
11550         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11551         GL_AlphaTest(false);
11552 }
11553
11554 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
11555 {
11556         // transparent surfaces get pushed off into the transparent queue
11557         int surfacelistindex;
11558         const msurface_t *surface;
11559         vec3_t tempcenter, center;
11560         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11561         {
11562                 surface = texturesurfacelist[surfacelistindex];
11563                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11564                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11565                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11566                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11567                 if (queueentity->transparent_offset) // transparent offset
11568                 {
11569                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
11570                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
11571                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
11572                 }
11573                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
11574         }
11575 }
11576
11577 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11578 {
11579         const entity_render_t *queueentity = r_refdef.scene.worldentity;
11580         CHECKGLERROR
11581         if (depthonly)
11582         {
11583                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11584                         return;
11585                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11586                         return;
11587                 RSurf_SetupDepthAndCulling();
11588                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11589                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11590         }
11591         else if (prepass)
11592         {
11593                 if (!rsurface.texture->currentnumlayers)
11594                         return;
11595                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11596                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11597                 else
11598                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11599         }
11600         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
11601         {
11602                 RSurf_SetupDepthAndCulling();
11603                 GL_AlphaTest(false);
11604                 R_Mesh_ColorPointer(NULL, 0, 0);
11605                 R_Mesh_ResetTextureState();
11606                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11607                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11608                 GL_DepthMask(true);
11609                 GL_BlendFunc(GL_ONE, GL_ZERO);
11610                 GL_Color(0, 0, 0, 1);
11611                 GL_DepthTest(writedepth);
11612                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11613         }
11614         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
11615         {
11616                 RSurf_SetupDepthAndCulling();
11617                 GL_AlphaTest(false);
11618                 R_Mesh_ColorPointer(NULL, 0, 0);
11619                 R_Mesh_ResetTextureState();
11620                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11621                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11622                 GL_DepthMask(true);
11623                 GL_BlendFunc(GL_ONE, GL_ZERO);
11624                 GL_DepthTest(true);
11625                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11626         }
11627         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11628                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11629         else if (!rsurface.texture->currentnumlayers)
11630                 return;
11631         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11632         {
11633                 // in the deferred case, transparent surfaces were queued during prepass
11634                 if (!r_shadow_usingdeferredprepass)
11635                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11636         }
11637         else
11638         {
11639                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11640                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11641         }
11642         CHECKGLERROR
11643 }
11644
11645 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11646 {
11647         int i, j;
11648         texture_t *texture;
11649         // break the surface list down into batches by texture and use of lightmapping
11650         for (i = 0;i < numsurfaces;i = j)
11651         {
11652                 j = i + 1;
11653                 // texture is the base texture pointer, rsurface.texture is the
11654                 // current frame/skin the texture is directing us to use (for example
11655                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11656                 // use skin 1 instead)
11657                 texture = surfacelist[i]->texture;
11658                 rsurface.texture = R_GetCurrentTexture(texture);
11659                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11660                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11661                 {
11662                         // if this texture is not the kind we want, skip ahead to the next one
11663                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11664                                 ;
11665                         continue;
11666                 }
11667                 // simply scan ahead until we find a different texture or lightmap state
11668                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11669                         ;
11670                 // render the range of surfaces
11671                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11672         }
11673 }
11674
11675 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
11676 {
11677         CHECKGLERROR
11678         if (depthonly)
11679         {
11680                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11681                         return;
11682                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11683                         return;
11684                 RSurf_SetupDepthAndCulling();
11685                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11686                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11687         }
11688         else if (prepass)
11689         {
11690                 if (!rsurface.texture->currentnumlayers)
11691                         return;
11692                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11693                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11694                 else
11695                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11696         }
11697         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
11698         {
11699                 RSurf_SetupDepthAndCulling();
11700                 GL_AlphaTest(false);
11701                 R_Mesh_ColorPointer(NULL, 0, 0);
11702                 R_Mesh_ResetTextureState();
11703                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11704                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11705                 GL_DepthMask(true);
11706                 GL_BlendFunc(GL_ONE, GL_ZERO);
11707                 GL_Color(0, 0, 0, 1);
11708                 GL_DepthTest(writedepth);
11709                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11710         }
11711         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11712         {
11713                 RSurf_SetupDepthAndCulling();
11714                 GL_AlphaTest(false);
11715                 R_Mesh_ColorPointer(NULL, 0, 0);
11716                 R_Mesh_ResetTextureState();
11717                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11718                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11719                 GL_DepthMask(true);
11720                 GL_BlendFunc(GL_ONE, GL_ZERO);
11721                 GL_DepthTest(true);
11722                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11723         }
11724         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11725                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11726         else if (!rsurface.texture->currentnumlayers)
11727                 return;
11728         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11729         {
11730                 // in the deferred case, transparent surfaces were queued during prepass
11731                 if (!r_shadow_usingdeferredprepass)
11732                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11733         }
11734         else
11735         {
11736                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11737                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11738         }
11739         CHECKGLERROR
11740 }
11741
11742 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11743 {
11744         int i, j;
11745         texture_t *texture;
11746         // break the surface list down into batches by texture and use of lightmapping
11747         for (i = 0;i < numsurfaces;i = j)
11748         {
11749                 j = i + 1;
11750                 // texture is the base texture pointer, rsurface.texture is the
11751                 // current frame/skin the texture is directing us to use (for example
11752                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11753                 // use skin 1 instead)
11754                 texture = surfacelist[i]->texture;
11755                 rsurface.texture = R_GetCurrentTexture(texture);
11756                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11757                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11758                 {
11759                         // if this texture is not the kind we want, skip ahead to the next one
11760                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11761                                 ;
11762                         continue;
11763                 }
11764                 // simply scan ahead until we find a different texture or lightmap state
11765                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11766                         ;
11767                 // render the range of surfaces
11768                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11769         }
11770 }
11771
11772 float locboxvertex3f[6*4*3] =
11773 {
11774         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11775         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11776         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11777         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11778         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11779         1,0,0, 0,0,0, 0,1,0, 1,1,0
11780 };
11781
11782 unsigned short locboxelements[6*2*3] =
11783 {
11784          0, 1, 2, 0, 2, 3,
11785          4, 5, 6, 4, 6, 7,
11786          8, 9,10, 8,10,11,
11787         12,13,14, 12,14,15,
11788         16,17,18, 16,18,19,
11789         20,21,22, 20,22,23
11790 };
11791
11792 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11793 {
11794         int i, j;
11795         cl_locnode_t *loc = (cl_locnode_t *)ent;
11796         vec3_t mins, size;
11797         float vertex3f[6*4*3];
11798         CHECKGLERROR
11799         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11800         GL_DepthMask(false);
11801         GL_DepthRange(0, 1);
11802         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11803         GL_DepthTest(true);
11804         GL_CullFace(GL_NONE);
11805         R_EntityMatrix(&identitymatrix);
11806
11807         R_Mesh_VertexPointer(vertex3f, 0, 0);
11808         R_Mesh_ColorPointer(NULL, 0, 0);
11809         R_Mesh_ResetTextureState();
11810         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11811
11812         i = surfacelist[0];
11813         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11814                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11815                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11816                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11817
11818         if (VectorCompare(loc->mins, loc->maxs))
11819         {
11820                 VectorSet(size, 2, 2, 2);
11821                 VectorMA(loc->mins, -0.5f, size, mins);
11822         }
11823         else
11824         {
11825                 VectorCopy(loc->mins, mins);
11826                 VectorSubtract(loc->maxs, loc->mins, size);
11827         }
11828
11829         for (i = 0;i < 6*4*3;)
11830                 for (j = 0;j < 3;j++, i++)
11831                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11832
11833         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11834 }
11835
11836 void R_DrawLocs(void)
11837 {
11838         int index;
11839         cl_locnode_t *loc, *nearestloc;
11840         vec3_t center;
11841         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11842         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11843         {
11844                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11845                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11846         }
11847 }
11848
11849 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11850 {
11851         if (decalsystem->decals)
11852                 Mem_Free(decalsystem->decals);
11853         memset(decalsystem, 0, sizeof(*decalsystem));
11854 }
11855
11856 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)
11857 {
11858         tridecal_t *decal;
11859         tridecal_t *decals;
11860         int i;
11861
11862         // expand or initialize the system
11863         if (decalsystem->maxdecals <= decalsystem->numdecals)
11864         {
11865                 decalsystem_t old = *decalsystem;
11866                 qboolean useshortelements;
11867                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11868                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11869                 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)));
11870                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11871                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11872                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11873                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11874                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11875                 if (decalsystem->numdecals)
11876                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11877                 if (old.decals)
11878                         Mem_Free(old.decals);
11879                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11880                         decalsystem->element3i[i] = i;
11881                 if (useshortelements)
11882                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11883                                 decalsystem->element3s[i] = i;
11884         }
11885
11886         // grab a decal and search for another free slot for the next one
11887         decals = decalsystem->decals;
11888         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11889         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11890                 ;
11891         decalsystem->freedecal = i;
11892         if (decalsystem->numdecals <= i)
11893                 decalsystem->numdecals = i + 1;
11894
11895         // initialize the decal
11896         decal->lived = 0;
11897         decal->triangleindex = triangleindex;
11898         decal->surfaceindex = surfaceindex;
11899         decal->decalsequence = decalsequence;
11900         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11901         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11902         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11903         decal->color4ub[0][3] = 255;
11904         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11905         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11906         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11907         decal->color4ub[1][3] = 255;
11908         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11909         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11910         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11911         decal->color4ub[2][3] = 255;
11912         decal->vertex3f[0][0] = v0[0];
11913         decal->vertex3f[0][1] = v0[1];
11914         decal->vertex3f[0][2] = v0[2];
11915         decal->vertex3f[1][0] = v1[0];
11916         decal->vertex3f[1][1] = v1[1];
11917         decal->vertex3f[1][2] = v1[2];
11918         decal->vertex3f[2][0] = v2[0];
11919         decal->vertex3f[2][1] = v2[1];
11920         decal->vertex3f[2][2] = v2[2];
11921         decal->texcoord2f[0][0] = t0[0];
11922         decal->texcoord2f[0][1] = t0[1];
11923         decal->texcoord2f[1][0] = t1[0];
11924         decal->texcoord2f[1][1] = t1[1];
11925         decal->texcoord2f[2][0] = t2[0];
11926         decal->texcoord2f[2][1] = t2[1];
11927 }
11928
11929 extern cvar_t cl_decals_bias;
11930 extern cvar_t cl_decals_models;
11931 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11932 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)
11933 {
11934         matrix4x4_t projection;
11935         decalsystem_t *decalsystem;
11936         qboolean dynamic;
11937         dp_model_t *model;
11938         const float *vertex3f;
11939         const msurface_t *surface;
11940         const msurface_t *surfaces;
11941         const int *surfacelist;
11942         const texture_t *texture;
11943         int numtriangles;
11944         int numsurfacelist;
11945         int surfacelistindex;
11946         int surfaceindex;
11947         int triangleindex;
11948         int cornerindex;
11949         int index;
11950         int numpoints;
11951         const int *e;
11952         float localorigin[3];
11953         float localnormal[3];
11954         float localmins[3];
11955         float localmaxs[3];
11956         float localsize;
11957         float v[9][3];
11958         float tc[9][2];
11959         float c[9][4];
11960         //float normal[3];
11961         float planes[6][4];
11962         float f;
11963         float points[2][9][3];
11964         float angles[3];
11965         float temp[3];
11966
11967         decalsystem = &ent->decalsystem;
11968         model = ent->model;
11969         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11970         {
11971                 R_DecalSystem_Reset(&ent->decalsystem);
11972                 return;
11973         }
11974
11975         if (!model->brush.data_nodes && !cl_decals_models.integer)
11976         {
11977                 if (decalsystem->model)
11978                         R_DecalSystem_Reset(decalsystem);
11979                 return;
11980         }
11981
11982         if (decalsystem->model != model)
11983                 R_DecalSystem_Reset(decalsystem);
11984         decalsystem->model = model;
11985
11986         RSurf_ActiveModelEntity(ent, false, false, false);
11987
11988         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11989         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11990         VectorNormalize(localnormal);
11991         localsize = worldsize*rsurface.inversematrixscale;
11992         localmins[0] = localorigin[0] - localsize;
11993         localmins[1] = localorigin[1] - localsize;
11994         localmins[2] = localorigin[2] - localsize;
11995         localmaxs[0] = localorigin[0] + localsize;
11996         localmaxs[1] = localorigin[1] + localsize;
11997         localmaxs[2] = localorigin[2] + localsize;
11998
11999         //VectorCopy(localnormal, planes[4]);
12000         //VectorVectors(planes[4], planes[2], planes[0]);
12001         AnglesFromVectors(angles, localnormal, NULL, false);
12002         AngleVectors(angles, planes[0], planes[2], planes[4]);
12003         VectorNegate(planes[0], planes[1]);
12004         VectorNegate(planes[2], planes[3]);
12005         VectorNegate(planes[4], planes[5]);
12006         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
12007         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
12008         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
12009         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
12010         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
12011         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
12012
12013 #if 1
12014 // works
12015 {
12016         matrix4x4_t forwardprojection;
12017         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
12018         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
12019 }
12020 #else
12021 // broken
12022 {
12023         float projectionvector[4][3];
12024         VectorScale(planes[0], ilocalsize, projectionvector[0]);
12025         VectorScale(planes[2], ilocalsize, projectionvector[1]);
12026         VectorScale(planes[4], ilocalsize, projectionvector[2]);
12027         projectionvector[0][0] = planes[0][0] * ilocalsize;
12028         projectionvector[0][1] = planes[1][0] * ilocalsize;
12029         projectionvector[0][2] = planes[2][0] * ilocalsize;
12030         projectionvector[1][0] = planes[0][1] * ilocalsize;
12031         projectionvector[1][1] = planes[1][1] * ilocalsize;
12032         projectionvector[1][2] = planes[2][1] * ilocalsize;
12033         projectionvector[2][0] = planes[0][2] * ilocalsize;
12034         projectionvector[2][1] = planes[1][2] * ilocalsize;
12035         projectionvector[2][2] = planes[2][2] * ilocalsize;
12036         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
12037         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
12038         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
12039         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
12040 }
12041 #endif
12042
12043         dynamic = model->surfmesh.isanimated;
12044         vertex3f = rsurface.modelvertex3f;
12045         numsurfacelist = model->nummodelsurfaces;
12046         surfacelist = model->sortedmodelsurfaces;
12047         surfaces = model->data_surfaces;
12048         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
12049         {
12050                 surfaceindex = surfacelist[surfacelistindex];
12051                 surface = surfaces + surfaceindex;
12052                 // check cull box first because it rejects more than any other check
12053                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
12054                         continue;
12055                 // skip transparent surfaces
12056                 texture = surface->texture;
12057                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12058                         continue;
12059                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12060                         continue;
12061                 numtriangles = surface->num_triangles;
12062                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
12063                 {
12064                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
12065                         {
12066                                 index = 3*e[cornerindex];
12067                                 VectorCopy(vertex3f + index, v[cornerindex]);
12068                         }
12069                         // cull backfaces
12070                         //TriangleNormal(v[0], v[1], v[2], normal);
12071                         //if (DotProduct(normal, localnormal) < 0.0f)
12072                         //      continue;
12073                         // clip by each of the box planes formed from the projection matrix
12074                         // if anything survives, we emit the decal
12075                         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]);
12076                         if (numpoints < 3)
12077                                 continue;
12078                         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]);
12079                         if (numpoints < 3)
12080                                 continue;
12081                         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]);
12082                         if (numpoints < 3)
12083                                 continue;
12084                         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]);
12085                         if (numpoints < 3)
12086                                 continue;
12087                         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]);
12088                         if (numpoints < 3)
12089                                 continue;
12090                         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]);
12091                         if (numpoints < 3)
12092                                 continue;
12093                         // some part of the triangle survived, so we have to accept it...
12094                         if (dynamic)
12095                         {
12096                                 // dynamic always uses the original triangle
12097                                 numpoints = 3;
12098                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
12099                                 {
12100                                         index = 3*e[cornerindex];
12101                                         VectorCopy(vertex3f + index, v[cornerindex]);
12102                                 }
12103                         }
12104                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
12105                         {
12106                                 // convert vertex positions to texcoords
12107                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
12108                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
12109                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
12110                                 // calculate distance fade from the projection origin
12111                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
12112                                 f = bound(0.0f, f, 1.0f);
12113                                 c[cornerindex][0] = r * f;
12114                                 c[cornerindex][1] = g * f;
12115                                 c[cornerindex][2] = b * f;
12116                                 c[cornerindex][3] = 1.0f;
12117                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
12118                         }
12119                         if (dynamic)
12120                                 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex+surface->num_firsttriangle, surfaceindex, decalsequence);
12121                         else
12122                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
12123                                         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);
12124                 }
12125         }
12126 }
12127
12128 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12129 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)
12130 {
12131         int renderentityindex;
12132         float worldmins[3];
12133         float worldmaxs[3];
12134         entity_render_t *ent;
12135
12136         if (!cl_decals_newsystem.integer)
12137                 return;
12138
12139         worldmins[0] = worldorigin[0] - worldsize;
12140         worldmins[1] = worldorigin[1] - worldsize;
12141         worldmins[2] = worldorigin[2] - worldsize;
12142         worldmaxs[0] = worldorigin[0] + worldsize;
12143         worldmaxs[1] = worldorigin[1] + worldsize;
12144         worldmaxs[2] = worldorigin[2] + worldsize;
12145
12146         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12147
12148         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12149         {
12150                 ent = r_refdef.scene.entities[renderentityindex];
12151                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12152                         continue;
12153
12154                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12155         }
12156 }
12157
12158 typedef struct r_decalsystem_splatqueue_s
12159 {
12160         vec3_t worldorigin;
12161         vec3_t worldnormal;
12162         float color[4];
12163         float tcrange[4];
12164         float worldsize;
12165         int decalsequence;
12166 }
12167 r_decalsystem_splatqueue_t;
12168
12169 int r_decalsystem_numqueued = 0;
12170 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12171
12172 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)
12173 {
12174         r_decalsystem_splatqueue_t *queue;
12175
12176         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12177                 return;
12178
12179         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12180         VectorCopy(worldorigin, queue->worldorigin);
12181         VectorCopy(worldnormal, queue->worldnormal);
12182         Vector4Set(queue->color, r, g, b, a);
12183         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12184         queue->worldsize = worldsize;
12185         queue->decalsequence = cl.decalsequence++;
12186 }
12187
12188 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12189 {
12190         int i;
12191         r_decalsystem_splatqueue_t *queue;
12192
12193         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12194                 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);
12195         r_decalsystem_numqueued = 0;
12196 }
12197
12198 extern cvar_t cl_decals_max;
12199 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12200 {
12201         int i;
12202         decalsystem_t *decalsystem = &ent->decalsystem;
12203         int numdecals;
12204         int killsequence;
12205         tridecal_t *decal;
12206         float frametime;
12207         float lifetime;
12208
12209         if (!decalsystem->numdecals)
12210                 return;
12211
12212         if (r_showsurfaces.integer)
12213                 return;
12214
12215         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12216         {
12217                 R_DecalSystem_Reset(decalsystem);
12218                 return;
12219         }
12220
12221         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
12222         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12223
12224         if (decalsystem->lastupdatetime)
12225                 frametime = (cl.time - decalsystem->lastupdatetime);
12226         else
12227                 frametime = 0;
12228         decalsystem->lastupdatetime = cl.time;
12229         decal = decalsystem->decals;
12230         numdecals = decalsystem->numdecals;
12231
12232         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12233         {
12234                 if (decal->color4ub[0][3])
12235                 {
12236                         decal->lived += frametime;
12237                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
12238                         {
12239                                 memset(decal, 0, sizeof(*decal));
12240                                 if (decalsystem->freedecal > i)
12241                                         decalsystem->freedecal = i;
12242                         }
12243                 }
12244         }
12245         decal = decalsystem->decals;
12246         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
12247                 numdecals--;
12248
12249         // collapse the array by shuffling the tail decals into the gaps
12250         for (;;)
12251         {
12252                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
12253                         decalsystem->freedecal++;
12254                 if (decalsystem->freedecal == numdecals)
12255                         break;
12256                 decal[decalsystem->freedecal] = decal[--numdecals];
12257         }
12258
12259         decalsystem->numdecals = numdecals;
12260
12261         if (numdecals <= 0)
12262         {
12263                 // if there are no decals left, reset decalsystem
12264                 R_DecalSystem_Reset(decalsystem);
12265         }
12266 }
12267
12268 extern skinframe_t *decalskinframe;
12269 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12270 {
12271         int i;
12272         decalsystem_t *decalsystem = &ent->decalsystem;
12273         int numdecals;
12274         tridecal_t *decal;
12275         float faderate;
12276         float alpha;
12277         float *v3f;
12278         float *c4f;
12279         float *t2f;
12280         const int *e;
12281         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12282         int numtris = 0;
12283
12284         numdecals = decalsystem->numdecals;
12285         if (!numdecals)
12286                 return;
12287
12288         if (r_showsurfaces.integer)
12289                 return;
12290
12291         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12292         {
12293                 R_DecalSystem_Reset(decalsystem);
12294                 return;
12295         }
12296
12297         // if the model is static it doesn't matter what value we give for
12298         // wantnormals and wanttangents, so this logic uses only rules applicable
12299         // to a model, knowing that they are meaningless otherwise
12300         if (ent == r_refdef.scene.worldentity)
12301                 RSurf_ActiveWorldEntity();
12302         else
12303                 RSurf_ActiveModelEntity(ent, false, false, false);
12304
12305         decalsystem->lastupdatetime = cl.time;
12306         decal = decalsystem->decals;
12307
12308         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12309
12310         // update vertex positions for animated models
12311         v3f = decalsystem->vertex3f;
12312         c4f = decalsystem->color4f;
12313         t2f = decalsystem->texcoord2f;
12314         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12315         {
12316                 if (!decal->color4ub[0][3])
12317                         continue;
12318
12319                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12320                         continue;
12321
12322                 // update color values for fading decals
12323                 if (decal->lived >= cl_decals_time.value)
12324                 {
12325                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12326                         alpha *= (1.0f/255.0f);
12327                 }
12328                 else
12329                         alpha = 1.0f/255.0f;
12330
12331                 c4f[ 0] = decal->color4ub[0][0] * alpha;
12332                 c4f[ 1] = decal->color4ub[0][1] * alpha;
12333                 c4f[ 2] = decal->color4ub[0][2] * alpha;
12334                 c4f[ 3] = 1;
12335                 c4f[ 4] = decal->color4ub[1][0] * alpha;
12336                 c4f[ 5] = decal->color4ub[1][1] * alpha;
12337                 c4f[ 6] = decal->color4ub[1][2] * alpha;
12338                 c4f[ 7] = 1;
12339                 c4f[ 8] = decal->color4ub[2][0] * alpha;
12340                 c4f[ 9] = decal->color4ub[2][1] * alpha;
12341                 c4f[10] = decal->color4ub[2][2] * alpha;
12342                 c4f[11] = 1;
12343
12344                 t2f[0] = decal->texcoord2f[0][0];
12345                 t2f[1] = decal->texcoord2f[0][1];
12346                 t2f[2] = decal->texcoord2f[1][0];
12347                 t2f[3] = decal->texcoord2f[1][1];
12348                 t2f[4] = decal->texcoord2f[2][0];
12349                 t2f[5] = decal->texcoord2f[2][1];
12350
12351                 // update vertex positions for animated models
12352                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
12353                 {
12354                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12355                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
12356                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
12357                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
12358                 }
12359                 else
12360                 {
12361                         VectorCopy(decal->vertex3f[0], v3f);
12362                         VectorCopy(decal->vertex3f[1], v3f + 3);
12363                         VectorCopy(decal->vertex3f[2], v3f + 6);
12364                 }
12365
12366                 if (r_refdef.fogenabled)
12367                 {
12368                         alpha = RSurf_FogVertex(v3f);
12369                         VectorScale(c4f, alpha, c4f);
12370                         alpha = RSurf_FogVertex(v3f + 3);
12371                         VectorScale(c4f + 4, alpha, c4f + 4);
12372                         alpha = RSurf_FogVertex(v3f + 6);
12373                         VectorScale(c4f + 8, alpha, c4f + 8);
12374                 }
12375
12376                 v3f += 9;
12377                 c4f += 12;
12378                 t2f += 6;
12379                 numtris++;
12380         }
12381
12382         if (numtris > 0)
12383         {
12384                 r_refdef.stats.drawndecals += numtris;
12385
12386                 // now render the decals all at once
12387                 // (this assumes they all use one particle font texture!)
12388                 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);
12389                 R_Mesh_ResetTextureState();
12390                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
12391                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
12392                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
12393                 GL_DepthMask(false);
12394                 GL_DepthRange(0, 1);
12395                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12396                 GL_DepthTest(true);
12397                 GL_CullFace(GL_NONE);
12398                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12399                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
12400                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
12401         }
12402 }
12403
12404 static void R_DrawModelDecals(void)
12405 {
12406         int i, numdecals;
12407
12408         // fade faster when there are too many decals
12409         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12410         for (i = 0;i < r_refdef.scene.numentities;i++)
12411                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12412
12413         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12414         for (i = 0;i < r_refdef.scene.numentities;i++)
12415                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12416                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12417
12418         R_DecalSystem_ApplySplatEntitiesQueue();
12419
12420         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12421         for (i = 0;i < r_refdef.scene.numentities;i++)
12422                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12423
12424         r_refdef.stats.totaldecals += numdecals;
12425
12426         if (r_showsurfaces.integer)
12427                 return;
12428
12429         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12430
12431         for (i = 0;i < r_refdef.scene.numentities;i++)
12432         {
12433                 if (!r_refdef.viewcache.entityvisible[i])
12434                         continue;
12435                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12436                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12437         }
12438 }
12439
12440 extern cvar_t mod_collision_bih;
12441 void R_DrawDebugModel(void)
12442 {
12443         entity_render_t *ent = rsurface.entity;
12444         int i, j, k, l, flagsmask;
12445         const msurface_t *surface;
12446         dp_model_t *model = ent->model;
12447         vec3_t v;
12448
12449         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12450
12451         R_Mesh_ColorPointer(NULL, 0, 0);
12452         R_Mesh_ResetTextureState();
12453         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12454         GL_DepthRange(0, 1);
12455         GL_DepthTest(!r_showdisabledepthtest.integer);
12456         GL_DepthMask(false);
12457         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12458
12459         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12460         {
12461                 int triangleindex;
12462                 int bihleafindex;
12463                 qboolean cullbox = ent == r_refdef.scene.worldentity;
12464                 const q3mbrush_t *brush;
12465                 const bih_t *bih = &model->collision_bih;
12466                 const bih_leaf_t *bihleaf;
12467                 float vertex3f[3][3];
12468                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12469                 cullbox = false;
12470                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12471                 {
12472                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12473                                 continue;
12474                         switch (bihleaf->type)
12475                         {
12476                         case BIH_BRUSH:
12477                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12478                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12479                                 {
12480                                         R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
12481                                         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);
12482                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
12483                                 }
12484                                 break;
12485                         case BIH_COLLISIONTRIANGLE:
12486                                 triangleindex = bihleaf->itemindex;
12487                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12488                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12489                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12490                                 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
12491                                 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);
12492                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
12493                                 break;
12494                         case BIH_RENDERTRIANGLE:
12495                                 triangleindex = bihleaf->itemindex;
12496                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12497                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12498                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12499                                 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
12500                                 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);
12501                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
12502                                 break;
12503                         }
12504                 }
12505         }
12506
12507         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12508
12509         if (r_showtris.integer || r_shownormals.integer)
12510         {
12511                 if (r_showdisabledepthtest.integer)
12512                 {
12513                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12514                         GL_DepthMask(false);
12515                 }
12516                 else
12517                 {
12518                         GL_BlendFunc(GL_ONE, GL_ZERO);
12519                         GL_DepthMask(true);
12520                 }
12521                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12522                 {
12523                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12524                                 continue;
12525                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12526                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12527                         {
12528                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
12529                                 if (r_showtris.value > 0)
12530                                 {
12531                                         if (!rsurface.texture->currentlayers->depthmask)
12532                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12533                                         else if (ent == r_refdef.scene.worldentity)
12534                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12535                                         else
12536                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12537                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
12538                                         R_Mesh_ColorPointer(NULL, 0, 0);
12539                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
12540                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
12541                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
12542                                         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);
12543                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
12544                                         CHECKGLERROR
12545                                 }
12546                                 if (r_shownormals.value < 0)
12547                                 {
12548                                         qglBegin(GL_LINES);
12549                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12550                                         {
12551                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12552                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12553                                                 qglVertex3f(v[0], v[1], v[2]);
12554                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
12555                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12556                                                 qglVertex3f(v[0], v[1], v[2]);
12557                                         }
12558                                         qglEnd();
12559                                         CHECKGLERROR
12560                                 }
12561                                 if (r_shownormals.value > 0)
12562                                 {
12563                                         qglBegin(GL_LINES);
12564                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12565                                         {
12566                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12567                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12568                                                 qglVertex3f(v[0], v[1], v[2]);
12569                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
12570                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12571                                                 qglVertex3f(v[0], v[1], v[2]);
12572                                         }
12573                                         qglEnd();
12574                                         CHECKGLERROR
12575                                         qglBegin(GL_LINES);
12576                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12577                                         {
12578                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12579                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12580                                                 qglVertex3f(v[0], v[1], v[2]);
12581                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
12582                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12583                                                 qglVertex3f(v[0], v[1], v[2]);
12584                                         }
12585                                         qglEnd();
12586                                         CHECKGLERROR
12587                                         qglBegin(GL_LINES);
12588                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12589                                         {
12590                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12591                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12592                                                 qglVertex3f(v[0], v[1], v[2]);
12593                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
12594                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12595                                                 qglVertex3f(v[0], v[1], v[2]);
12596                                         }
12597                                         qglEnd();
12598                                         CHECKGLERROR
12599                                 }
12600                         }
12601                 }
12602                 rsurface.texture = NULL;
12603         }
12604 }
12605
12606 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
12607 int r_maxsurfacelist = 0;
12608 const msurface_t **r_surfacelist = NULL;
12609 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12610 {
12611         int i, j, endj, flagsmask;
12612         dp_model_t *model = r_refdef.scene.worldmodel;
12613         msurface_t *surfaces;
12614         unsigned char *update;
12615         int numsurfacelist = 0;
12616         if (model == NULL)
12617                 return;
12618
12619         if (r_maxsurfacelist < model->num_surfaces)
12620         {
12621                 r_maxsurfacelist = model->num_surfaces;
12622                 if (r_surfacelist)
12623                         Mem_Free((msurface_t**)r_surfacelist);
12624                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12625         }
12626
12627         RSurf_ActiveWorldEntity();
12628
12629         surfaces = model->data_surfaces;
12630         update = model->brushq1.lightmapupdateflags;
12631
12632         // update light styles on this submodel
12633         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12634         {
12635                 model_brush_lightstyleinfo_t *style;
12636                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12637                 {
12638                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12639                         {
12640                                 int *list = style->surfacelist;
12641                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12642                                 for (j = 0;j < style->numsurfaces;j++)
12643                                         update[list[j]] = true;
12644                         }
12645                 }
12646         }
12647
12648         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12649
12650         if (debug)
12651         {
12652                 R_DrawDebugModel();
12653                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12654                 return;
12655         }
12656
12657         rsurface.uselightmaptexture = false;
12658         rsurface.texture = NULL;
12659         rsurface.rtlight = NULL;
12660         numsurfacelist = 0;
12661         // add visible surfaces to draw list
12662         for (i = 0;i < model->nummodelsurfaces;i++)
12663         {
12664                 j = model->sortedmodelsurfaces[i];
12665                 if (r_refdef.viewcache.world_surfacevisible[j])
12666                         r_surfacelist[numsurfacelist++] = surfaces + j;
12667         }
12668         // update lightmaps if needed
12669         if (model->brushq1.firstrender)
12670         {
12671                 model->brushq1.firstrender = false;
12672                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12673                         if (update[j])
12674                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12675         }
12676         else if (update)
12677         {
12678                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12679                         if (r_refdef.viewcache.world_surfacevisible[j])
12680                                 if (update[j])
12681                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12682         }
12683         // don't do anything if there were no surfaces
12684         if (!numsurfacelist)
12685         {
12686                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12687                 return;
12688         }
12689         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12690         GL_AlphaTest(false);
12691
12692         // add to stats if desired
12693         if (r_speeds.integer && !skysurfaces && !depthonly)
12694         {
12695                 r_refdef.stats.world_surfaces += numsurfacelist;
12696                 for (j = 0;j < numsurfacelist;j++)
12697                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12698         }
12699
12700         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12701 }
12702
12703 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12704 {
12705         int i, j, endj, flagsmask;
12706         dp_model_t *model = ent->model;
12707         msurface_t *surfaces;
12708         unsigned char *update;
12709         int numsurfacelist = 0;
12710         if (model == NULL)
12711                 return;
12712
12713         if (r_maxsurfacelist < model->num_surfaces)
12714         {
12715                 r_maxsurfacelist = model->num_surfaces;
12716                 if (r_surfacelist)
12717                         Mem_Free((msurface_t **)r_surfacelist);
12718                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12719         }
12720
12721         // if the model is static it doesn't matter what value we give for
12722         // wantnormals and wanttangents, so this logic uses only rules applicable
12723         // to a model, knowing that they are meaningless otherwise
12724         if (ent == r_refdef.scene.worldentity)
12725                 RSurf_ActiveWorldEntity();
12726         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12727                 RSurf_ActiveModelEntity(ent, false, false, false);
12728         else if (prepass)
12729                 RSurf_ActiveModelEntity(ent, true, true, true);
12730         else if (depthonly)
12731         {
12732                 switch (vid.renderpath)
12733                 {
12734                 case RENDERPATH_GL20:
12735                 case RENDERPATH_CGGL:
12736                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12737                         break;
12738                 case RENDERPATH_GL13:
12739                 case RENDERPATH_GL11:
12740                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12741                         break;
12742                 }
12743         }
12744         else
12745         {
12746                 switch (vid.renderpath)
12747                 {
12748                 case RENDERPATH_GL20:
12749                 case RENDERPATH_CGGL:
12750                         RSurf_ActiveModelEntity(ent, true, true, false);
12751                         break;
12752                 case RENDERPATH_GL13:
12753                 case RENDERPATH_GL11:
12754                         RSurf_ActiveModelEntity(ent, true, false, false);
12755                         break;
12756                 }
12757         }
12758
12759         surfaces = model->data_surfaces;
12760         update = model->brushq1.lightmapupdateflags;
12761
12762         // update light styles
12763         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12764         {
12765                 model_brush_lightstyleinfo_t *style;
12766                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12767                 {
12768                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12769                         {
12770                                 int *list = style->surfacelist;
12771                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12772                                 for (j = 0;j < style->numsurfaces;j++)
12773                                         update[list[j]] = true;
12774                         }
12775                 }
12776         }
12777
12778         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12779
12780         if (debug)
12781         {
12782                 R_DrawDebugModel();
12783                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12784                 return;
12785         }
12786
12787         rsurface.uselightmaptexture = false;
12788         rsurface.texture = NULL;
12789         rsurface.rtlight = NULL;
12790         numsurfacelist = 0;
12791         // add visible surfaces to draw list
12792         for (i = 0;i < model->nummodelsurfaces;i++)
12793                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12794         // don't do anything if there were no surfaces
12795         if (!numsurfacelist)
12796         {
12797                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12798                 return;
12799         }
12800         // update lightmaps if needed
12801         if (update)
12802         {
12803                 int updated = 0;
12804                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12805                 {
12806                         if (update[j])
12807                         {
12808                                 updated++;
12809                                 R_BuildLightMap(ent, surfaces + j);
12810                         }
12811                 }
12812         }
12813         if (update)
12814                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12815                         if (update[j])
12816                                 R_BuildLightMap(ent, surfaces + j);
12817         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12818         GL_AlphaTest(false);
12819
12820         // add to stats if desired
12821         if (r_speeds.integer && !skysurfaces && !depthonly)
12822         {
12823                 r_refdef.stats.entities_surfaces += numsurfacelist;
12824                 for (j = 0;j < numsurfacelist;j++)
12825                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12826         }
12827
12828         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12829 }
12830
12831 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12832 {
12833         static texture_t texture;
12834         static msurface_t surface;
12835         const msurface_t *surfacelist = &surface;
12836
12837         // fake enough texture and surface state to render this geometry
12838
12839         texture.update_lastrenderframe = -1; // regenerate this texture
12840         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12841         texture.currentskinframe = skinframe;
12842         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12843         texture.offsetmapping = OFFSETMAPPING_OFF;
12844         texture.offsetscale = 1;
12845         texture.specularscalemod = 1;
12846         texture.specularpowermod = 1;
12847
12848         surface.texture = &texture;
12849         surface.num_triangles = numtriangles;
12850         surface.num_firsttriangle = firsttriangle;
12851         surface.num_vertices = numvertices;
12852         surface.num_firstvertex = firstvertex;
12853
12854         // now render it
12855         rsurface.texture = R_GetCurrentTexture(surface.texture);
12856         rsurface.uselightmaptexture = false;
12857         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12858 }
12859
12860 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)
12861 {
12862         static msurface_t surface;
12863         const msurface_t *surfacelist = &surface;
12864
12865         // fake enough texture and surface state to render this geometry
12866
12867         surface.texture = texture;
12868         surface.num_triangles = numtriangles;
12869         surface.num_firsttriangle = firsttriangle;
12870         surface.num_vertices = numvertices;
12871         surface.num_firstvertex = firstvertex;
12872
12873         // now render it
12874         rsurface.texture = R_GetCurrentTexture(surface.texture);
12875         rsurface.uselightmaptexture = false;
12876         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12877 }