]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
add back VorteX's "lightweight shader parameter" system, but have it detect cvar...
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30
31 #ifdef SUPPORTD3D
32 #include <d3d9.h>
33 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
34 #endif
35
36 mempool_t *r_main_mempool;
37 rtexturepool_t *r_main_texturepool;
38
39 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
40
41 static qboolean r_loadnormalmap;
42 static qboolean r_loadgloss;
43 qboolean r_loadfog;
44 static qboolean r_loaddds;
45 static qboolean r_savedds;
46
47 //
48 // screen size info
49 //
50 r_refdef_t r_refdef;
51
52 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
53 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
54 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
55 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
56 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
57 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
59 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
60
61 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
62 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
63 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
64 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
65 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
66
67 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
68 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
69 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
70 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
71 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
72 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
73 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
74 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
75 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
76 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
77 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
79 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
80 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
81 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
82 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
83 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
84 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
85 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
86 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
87 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
88 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
89 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
90 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
91 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
92 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
93 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
94 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
95
96 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
97 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
98 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
99
100 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
101 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
102 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
103 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."};
104 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
105 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
106 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
107 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."};
108 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
109 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
110 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
111 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
112 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"};
113 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"};
114 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
115 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
117 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
118 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"};
119
120 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
121 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
122 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
123 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
124 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
125 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
126 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
127 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
128
129 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)"};
130 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"};
131
132 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
133 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
137
138 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
139 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
140 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
141
142 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)"};
143 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
144 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
145 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
146 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
147 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)"};
148 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)"};
149 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)"};
150 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)"};
151
152 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)"};
153 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
154 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"};
155 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
156 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
157 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
158
159 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
160 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
161 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
162 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
163
164 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
165 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
166 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
167 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
168 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
169 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
170 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
171
172 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
173 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
174 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
175 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)"};
176
177 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"};
178
179 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"};
180
181 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
182
183 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
184 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"};
185 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
186 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
187 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
188 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
189 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)"};
190
191 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
192 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
193
194 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)"};
195
196 extern cvar_t v_glslgamma;
197
198 extern qboolean v_flipped_state;
199
200 static struct r_bloomstate_s
201 {
202         qboolean enabled;
203         qboolean hdr;
204
205         int bloomwidth, bloomheight;
206
207         int screentexturewidth, screentextureheight;
208         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
209
210         int bloomtexturewidth, bloomtextureheight;
211         rtexture_t *texture_bloom;
212
213         // arrays for rendering the screen passes
214         float screentexcoord2f[8];
215         float bloomtexcoord2f[8];
216         float offsettexcoord2f[8];
217
218         r_viewport_t viewport;
219 }
220 r_bloomstate;
221
222 r_waterstate_t r_waterstate;
223
224 /// shadow volume bsp struct with automatically growing nodes buffer
225 svbsp_t r_svbsp;
226
227 rtexture_t *r_texture_blanknormalmap;
228 rtexture_t *r_texture_white;
229 rtexture_t *r_texture_grey128;
230 rtexture_t *r_texture_black;
231 rtexture_t *r_texture_notexture;
232 rtexture_t *r_texture_whitecube;
233 rtexture_t *r_texture_normalizationcube;
234 rtexture_t *r_texture_fogattenuation;
235 rtexture_t *r_texture_fogheighttexture;
236 rtexture_t *r_texture_gammaramps;
237 unsigned int r_texture_gammaramps_serial;
238 //rtexture_t *r_texture_fogintensity;
239 rtexture_t *r_texture_reflectcube;
240
241 // TODO: hash lookups?
242 typedef struct cubemapinfo_s
243 {
244         char basename[64];
245         rtexture_t *texture;
246 }
247 cubemapinfo_t;
248
249 int r_texture_numcubemaps;
250 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
251
252 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
253 unsigned int r_numqueries;
254 unsigned int r_maxqueries;
255
256 typedef struct r_qwskincache_s
257 {
258         char name[MAX_QPATH];
259         skinframe_t *skinframe;
260 }
261 r_qwskincache_t;
262
263 static r_qwskincache_t *r_qwskincache;
264 static int r_qwskincache_size;
265
266 /// vertex coordinates for a quad that covers the screen exactly
267 extern const float r_screenvertex3f[12];
268 extern const float r_d3dscreenvertex3f[12];
269 const float r_screenvertex3f[12] =
270 {
271         0, 0, 0,
272         1, 0, 0,
273         1, 1, 0,
274         0, 1, 0
275 };
276 const float r_d3dscreenvertex3f[12] =
277 {
278         0, 1, 0,
279         1, 1, 0,
280         1, 0, 0,
281         0, 0, 0
282 };
283
284 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
285 {
286         int i;
287         for (i = 0;i < verts;i++)
288         {
289                 out[0] = in[0] * r;
290                 out[1] = in[1] * g;
291                 out[2] = in[2] * b;
292                 out[3] = in[3];
293                 in += 4;
294                 out += 4;
295         }
296 }
297
298 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
299 {
300         int i;
301         for (i = 0;i < verts;i++)
302         {
303                 out[0] = r;
304                 out[1] = g;
305                 out[2] = b;
306                 out[3] = a;
307                 out += 4;
308         }
309 }
310
311 // FIXME: move this to client?
312 void FOG_clear(void)
313 {
314         if (gamemode == GAME_NEHAHRA)
315         {
316                 Cvar_Set("gl_fogenable", "0");
317                 Cvar_Set("gl_fogdensity", "0.2");
318                 Cvar_Set("gl_fogred", "0.3");
319                 Cvar_Set("gl_foggreen", "0.3");
320                 Cvar_Set("gl_fogblue", "0.3");
321         }
322         r_refdef.fog_density = 0;
323         r_refdef.fog_red = 0;
324         r_refdef.fog_green = 0;
325         r_refdef.fog_blue = 0;
326         r_refdef.fog_alpha = 1;
327         r_refdef.fog_start = 0;
328         r_refdef.fog_end = 16384;
329         r_refdef.fog_height = 1<<30;
330         r_refdef.fog_fadedepth = 128;
331         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
332 }
333
334 static void R_BuildBlankTextures(void)
335 {
336         unsigned char data[4];
337         data[2] = 128; // normal X
338         data[1] = 128; // normal Y
339         data[0] = 255; // normal Z
340         data[3] = 128; // height
341         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
342         data[0] = 255;
343         data[1] = 255;
344         data[2] = 255;
345         data[3] = 255;
346         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
347         data[0] = 128;
348         data[1] = 128;
349         data[2] = 128;
350         data[3] = 255;
351         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
352         data[0] = 0;
353         data[1] = 0;
354         data[2] = 0;
355         data[3] = 255;
356         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
357 }
358
359 static void R_BuildNoTexture(void)
360 {
361         int x, y;
362         unsigned char pix[16][16][4];
363         // this makes a light grey/dark grey checkerboard texture
364         for (y = 0;y < 16;y++)
365         {
366                 for (x = 0;x < 16;x++)
367                 {
368                         if ((y < 8) ^ (x < 8))
369                         {
370                                 pix[y][x][0] = 128;
371                                 pix[y][x][1] = 128;
372                                 pix[y][x][2] = 128;
373                                 pix[y][x][3] = 255;
374                         }
375                         else
376                         {
377                                 pix[y][x][0] = 64;
378                                 pix[y][x][1] = 64;
379                                 pix[y][x][2] = 64;
380                                 pix[y][x][3] = 255;
381                         }
382                 }
383         }
384         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
385 }
386
387 static void R_BuildWhiteCube(void)
388 {
389         unsigned char data[6*1*1*4];
390         memset(data, 255, sizeof(data));
391         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
392 }
393
394 static void R_BuildNormalizationCube(void)
395 {
396         int x, y, side;
397         vec3_t v;
398         vec_t s, t, intensity;
399 #define NORMSIZE 64
400         unsigned char *data;
401         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
402         for (side = 0;side < 6;side++)
403         {
404                 for (y = 0;y < NORMSIZE;y++)
405                 {
406                         for (x = 0;x < NORMSIZE;x++)
407                         {
408                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
409                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
410                                 switch(side)
411                                 {
412                                 default:
413                                 case 0:
414                                         v[0] = 1;
415                                         v[1] = -t;
416                                         v[2] = -s;
417                                         break;
418                                 case 1:
419                                         v[0] = -1;
420                                         v[1] = -t;
421                                         v[2] = s;
422                                         break;
423                                 case 2:
424                                         v[0] = s;
425                                         v[1] = 1;
426                                         v[2] = t;
427                                         break;
428                                 case 3:
429                                         v[0] = s;
430                                         v[1] = -1;
431                                         v[2] = -t;
432                                         break;
433                                 case 4:
434                                         v[0] = s;
435                                         v[1] = -t;
436                                         v[2] = 1;
437                                         break;
438                                 case 5:
439                                         v[0] = -s;
440                                         v[1] = -t;
441                                         v[2] = -1;
442                                         break;
443                                 }
444                                 intensity = 127.0f / sqrt(DotProduct(v, v));
445                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
446                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
447                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
448                                 data[((side*64+y)*64+x)*4+3] = 255;
449                         }
450                 }
451         }
452         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
453         Mem_Free(data);
454 }
455
456 static void R_BuildFogTexture(void)
457 {
458         int x, b;
459 #define FOGWIDTH 256
460         unsigned char data1[FOGWIDTH][4];
461         //unsigned char data2[FOGWIDTH][4];
462         double d, r, alpha;
463
464         r_refdef.fogmasktable_start = r_refdef.fog_start;
465         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
466         r_refdef.fogmasktable_range = r_refdef.fogrange;
467         r_refdef.fogmasktable_density = r_refdef.fog_density;
468
469         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
470         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
471         {
472                 d = (x * r - r_refdef.fogmasktable_start);
473                 if(developer_extra.integer)
474                         Con_DPrintf("%f ", d);
475                 d = max(0, d);
476                 if (r_fog_exp2.integer)
477                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
478                 else
479                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
480                 if(developer_extra.integer)
481                         Con_DPrintf(" : %f ", alpha);
482                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
483                 if(developer_extra.integer)
484                         Con_DPrintf(" = %f\n", alpha);
485                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
486         }
487
488         for (x = 0;x < FOGWIDTH;x++)
489         {
490                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
491                 data1[x][0] = b;
492                 data1[x][1] = b;
493                 data1[x][2] = b;
494                 data1[x][3] = 255;
495                 //data2[x][0] = 255 - b;
496                 //data2[x][1] = 255 - b;
497                 //data2[x][2] = 255 - b;
498                 //data2[x][3] = 255;
499         }
500         if (r_texture_fogattenuation)
501         {
502                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
503                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
504         }
505         else
506         {
507                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
508                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
509         }
510 }
511
512 static void R_BuildFogHeightTexture(void)
513 {
514         unsigned char *inpixels;
515         int size;
516         int x;
517         int y;
518         int j;
519         float c[4];
520         float f;
521         inpixels = NULL;
522         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
523         if (r_refdef.fogheighttexturename[0])
524                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
525         if (!inpixels)
526         {
527                 r_refdef.fog_height_tablesize = 0;
528                 if (r_texture_fogheighttexture)
529                         R_FreeTexture(r_texture_fogheighttexture);
530                 r_texture_fogheighttexture = NULL;
531                 if (r_refdef.fog_height_table2d)
532                         Mem_Free(r_refdef.fog_height_table2d);
533                 r_refdef.fog_height_table2d = NULL;
534                 if (r_refdef.fog_height_table1d)
535                         Mem_Free(r_refdef.fog_height_table1d);
536                 r_refdef.fog_height_table1d = NULL;
537                 return;
538         }
539         size = image_width;
540         r_refdef.fog_height_tablesize = size;
541         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
542         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
543         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
544         Mem_Free(inpixels);
545         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
546         // average fog color table accounting for every fog layer between a point
547         // and the camera.  (Note: attenuation is handled separately!)
548         for (y = 0;y < size;y++)
549         {
550                 for (x = 0;x < size;x++)
551                 {
552                         Vector4Clear(c);
553                         f = 0;
554                         if (x < y)
555                         {
556                                 for (j = x;j <= y;j++)
557                                 {
558                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
559                                         f++;
560                                 }
561                         }
562                         else
563                         {
564                                 for (j = x;j >= y;j--)
565                                 {
566                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
567                                         f++;
568                                 }
569                         }
570                         f = 1.0f / f;
571                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
572                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
573                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
574                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
575                 }
576         }
577         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
578 }
579
580 //=======================================================================================================================================================
581
582 static const char *builtinshaderstring =
583 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
584 "// written by Forest 'LordHavoc' Hale\n"
585 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
586 "\n"
587 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
588 "# define USEFOG\n"
589 "#endif\n"
590 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
591 "#define USELIGHTMAP\n"
592 "#endif\n"
593 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
594 "#define USEEYEVECTOR\n"
595 "#endif\n"
596 "\n"
597 "#ifdef USESHADOWMAP2D\n"
598 "# ifdef GL_EXT_gpu_shader4\n"
599 "#   extension GL_EXT_gpu_shader4 : enable\n"
600 "# endif\n"
601 "# ifdef GL_ARB_texture_gather\n"
602 "#   extension GL_ARB_texture_gather : enable\n"
603 "# else\n"
604 "#   ifdef GL_AMD_texture_texture4\n"
605 "#     extension GL_AMD_texture_texture4 : enable\n"
606 "#   endif\n"
607 "# endif\n"
608 "#endif\n"
609 "\n"
610 "//#ifdef USESHADOWSAMPLER\n"
611 "//# extension GL_ARB_shadow : enable\n"
612 "//#endif\n"
613 "\n"
614 "//#ifdef __GLSL_CG_DATA_TYPES\n"
615 "//# define myhalf half\n"
616 "//# define myhalf2 half2\n"
617 "//# define myhalf3 half3\n"
618 "//# define myhalf4 half4\n"
619 "//#else\n"
620 "# define myhalf float\n"
621 "# define myhalf2 vec2\n"
622 "# define myhalf3 vec3\n"
623 "# define myhalf4 vec4\n"
624 "//#endif\n"
625 "\n"
626 "#ifdef VERTEX_SHADER\n"
627 "uniform mat4 ModelViewProjectionMatrix;\n"
628 "#endif\n"
629 "\n"
630 "#ifdef MODE_DEPTH_OR_SHADOW\n"
631 "#ifdef VERTEX_SHADER\n"
632 "void main(void)\n"
633 "{\n"
634 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
635 "}\n"
636 "#endif\n"
637 "#else // !MODE_DEPTH_ORSHADOW\n"
638 "\n"
639 "\n"
640 "\n"
641 "\n"
642 "#ifdef MODE_SHOWDEPTH\n"
643 "#ifdef VERTEX_SHADER\n"
644 "void main(void)\n"
645 "{\n"
646 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
647 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
648 "}\n"
649 "#endif\n"
650 "\n"
651 "#ifdef FRAGMENT_SHADER\n"
652 "void main(void)\n"
653 "{\n"
654 "       gl_FragColor = gl_Color;\n"
655 "}\n"
656 "#endif\n"
657 "#else // !MODE_SHOWDEPTH\n"
658 "\n"
659 "\n"
660 "\n"
661 "\n"
662 "#ifdef MODE_POSTPROCESS\n"
663 "varying vec2 TexCoord1;\n"
664 "varying vec2 TexCoord2;\n"
665 "\n"
666 "#ifdef VERTEX_SHADER\n"
667 "void main(void)\n"
668 "{\n"
669 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
670 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
671 "#ifdef USEBLOOM\n"
672 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
673 "#endif\n"
674 "}\n"
675 "#endif\n"
676 "\n"
677 "#ifdef FRAGMENT_SHADER\n"
678 "uniform sampler2D Texture_First;\n"
679 "#ifdef USEBLOOM\n"
680 "uniform sampler2D Texture_Second;\n"
681 "uniform vec4 BloomColorSubtract;\n"
682 "#endif\n"
683 "#ifdef USEGAMMARAMPS\n"
684 "uniform sampler2D Texture_GammaRamps;\n"
685 "#endif\n"
686 "#ifdef USESATURATION\n"
687 "uniform float Saturation;\n"
688 "#endif\n"
689 "#ifdef USEVIEWTINT\n"
690 "uniform vec4 ViewTintColor;\n"
691 "#endif\n"
692 "//uncomment these if you want to use them:\n"
693 "uniform vec4 UserVec1;\n"
694 "uniform vec4 UserVec2;\n"
695 "// uniform vec4 UserVec3;\n"
696 "// uniform vec4 UserVec4;\n"
697 "// uniform float ClientTime;\n"
698 "uniform vec2 PixelSize;\n"
699 "void main(void)\n"
700 "{\n"
701 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
702 "#ifdef USEBLOOM\n"
703 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
704 "#endif\n"
705 "#ifdef USEVIEWTINT\n"
706 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
707 "#endif\n"
708 "\n"
709 "#ifdef USEPOSTPROCESSING\n"
710 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
711 "// 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"
712 "       float sobel = 1.0;\n"
713 "       // vec2 ts = textureSize(Texture_First, 0);\n"
714 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
715 "       vec2 px = PixelSize;\n"
716 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
717 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
718 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
719 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
720 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
721 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
722 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
723 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
724 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
725 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
726 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
727 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
728 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
729 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
730 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
731 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
732 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
733 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
734 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
735 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
736 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
737 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
738 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
739 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
740 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
741 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
742 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
743 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
744 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
745 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
746 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
747 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
748 "#endif\n"
749 "\n"
750 "#ifdef USESATURATION\n"
751 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
752 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
753 "       // 'vampire sight' effect, wheres red is compensated\n"
754 "       #ifdef SATURATION_REDCOMPENSATE\n"
755 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
756 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
757 "               gl_FragColor.r += rboost;\n"
758 "       #else\n"
759 "               // normal desaturation\n"
760 "               //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
761 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
762 "       #endif\n"
763 "#endif\n"
764 "\n"
765 "#ifdef USEGAMMARAMPS\n"
766 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
767 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
768 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
769 "#endif\n"
770 "}\n"
771 "#endif\n"
772 "#else // !MODE_POSTPROCESS\n"
773 "\n"
774 "\n"
775 "\n"
776 "\n"
777 "#ifdef MODE_GENERIC\n"
778 "#ifdef USEDIFFUSE\n"
779 "varying vec2 TexCoord1;\n"
780 "#endif\n"
781 "#ifdef USESPECULAR\n"
782 "varying vec2 TexCoord2;\n"
783 "#endif\n"
784 "#ifdef VERTEX_SHADER\n"
785 "void main(void)\n"
786 "{\n"
787 "       gl_FrontColor = gl_Color;\n"
788 "#ifdef USEDIFFUSE\n"
789 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
790 "#endif\n"
791 "#ifdef USESPECULAR\n"
792 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
793 "#endif\n"
794 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
795 "}\n"
796 "#endif\n"
797 "\n"
798 "#ifdef FRAGMENT_SHADER\n"
799 "#ifdef USEDIFFUSE\n"
800 "uniform sampler2D Texture_First;\n"
801 "#endif\n"
802 "#ifdef USESPECULAR\n"
803 "uniform sampler2D Texture_Second;\n"
804 "#endif\n"
805 "\n"
806 "void main(void)\n"
807 "{\n"
808 "       gl_FragColor = gl_Color;\n"
809 "#ifdef USEDIFFUSE\n"
810 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
811 "#endif\n"
812 "\n"
813 "#ifdef USESPECULAR\n"
814 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
815 "# ifdef USECOLORMAPPING\n"
816 "       gl_FragColor *= tex2;\n"
817 "# endif\n"
818 "# ifdef USEGLOW\n"
819 "       gl_FragColor += tex2;\n"
820 "# endif\n"
821 "# ifdef USEVERTEXTEXTUREBLEND\n"
822 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
823 "# endif\n"
824 "#endif\n"
825 "}\n"
826 "#endif\n"
827 "#else // !MODE_GENERIC\n"
828 "\n"
829 "\n"
830 "\n"
831 "\n"
832 "#ifdef MODE_BLOOMBLUR\n"
833 "varying TexCoord;\n"
834 "#ifdef VERTEX_SHADER\n"
835 "void main(void)\n"
836 "{\n"
837 "       gl_FrontColor = gl_Color;\n"
838 "       TexCoord = gl_MultiTexCoord0.xy;\n"
839 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
840 "}\n"
841 "#endif\n"
842 "\n"
843 "#ifdef FRAGMENT_SHADER\n"
844 "uniform sampler2D Texture_First;\n"
845 "uniform vec4 BloomBlur_Parameters;\n"
846 "\n"
847 "void main(void)\n"
848 "{\n"
849 "       int i;\n"
850 "       vec2 tc = TexCoord;\n"
851 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
852 "       tc += BloomBlur_Parameters.xy;\n"
853 "       for (i = 1;i < SAMPLES;i++)\n"
854 "       {\n"
855 "               color += texture2D(Texture_First, tc).rgb;\n"
856 "               tc += BloomBlur_Parameters.xy;\n"
857 "       }\n"
858 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
859 "}\n"
860 "#endif\n"
861 "#else // !MODE_BLOOMBLUR\n"
862 "#ifdef MODE_REFRACTION\n"
863 "varying vec2 TexCoord;\n"
864 "varying vec4 ModelViewProjectionPosition;\n"
865 "uniform mat4 TexMatrix;\n"
866 "#ifdef VERTEX_SHADER\n"
867 "\n"
868 "void main(void)\n"
869 "{\n"
870 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
871 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
872 "       ModelViewProjectionPosition = gl_Position;\n"
873 "}\n"
874 "#endif\n"
875 "\n"
876 "#ifdef FRAGMENT_SHADER\n"
877 "uniform sampler2D Texture_Normal;\n"
878 "uniform sampler2D Texture_Refraction;\n"
879 "uniform sampler2D Texture_Reflection;\n"
880 "\n"
881 "uniform vec4 DistortScaleRefractReflect;\n"
882 "uniform vec4 ScreenScaleRefractReflect;\n"
883 "uniform vec4 ScreenCenterRefractReflect;\n"
884 "uniform vec4 RefractColor;\n"
885 "uniform vec4 ReflectColor;\n"
886 "uniform float ReflectFactor;\n"
887 "uniform float ReflectOffset;\n"
888 "\n"
889 "void main(void)\n"
890 "{\n"
891 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
892 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
893 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
894 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
895 "       // FIXME temporary hack to detect the case that the reflection\n"
896 "       // gets blackened at edges due to leaving the area that contains actual\n"
897 "       // content.\n"
898 "       // Remove this 'ack once we have a better way to stop this thing from\n"
899 "       // 'appening.\n"
900 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
901 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
902 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
903 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
904 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
905 "       gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
906 "}\n"
907 "#endif\n"
908 "#else // !MODE_REFRACTION\n"
909 "\n"
910 "\n"
911 "\n"
912 "\n"
913 "#ifdef MODE_WATER\n"
914 "varying vec2 TexCoord;\n"
915 "varying vec3 EyeVector;\n"
916 "varying vec4 ModelViewProjectionPosition;\n"
917 "#ifdef VERTEX_SHADER\n"
918 "uniform vec3 EyePosition;\n"
919 "uniform mat4 TexMatrix;\n"
920 "\n"
921 "void main(void)\n"
922 "{\n"
923 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
924 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
925 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
926 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
927 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
928 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
929 "       ModelViewProjectionPosition = gl_Position;\n"
930 "}\n"
931 "#endif\n"
932 "\n"
933 "#ifdef FRAGMENT_SHADER\n"
934 "uniform sampler2D Texture_Normal;\n"
935 "uniform sampler2D Texture_Refraction;\n"
936 "uniform sampler2D Texture_Reflection;\n"
937 "\n"
938 "uniform vec4 DistortScaleRefractReflect;\n"
939 "uniform vec4 ScreenScaleRefractReflect;\n"
940 "uniform vec4 ScreenCenterRefractReflect;\n"
941 "uniform vec4 RefractColor;\n"
942 "uniform vec4 ReflectColor;\n"
943 "uniform float ReflectFactor;\n"
944 "uniform float ReflectOffset;\n"
945 "uniform float ClientTime;\n"
946 "#ifdef USENORMALMAPSCROLLBLEND\n"
947 "uniform vec2 NormalmapScrollBlend;\n"
948 "#endif\n"
949 "\n"
950 "void main(void)\n"
951 "{\n"
952 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
953 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
954 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
955 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
956 "       // slight water animation via 2 layer scrolling (todo: tweak)\n"
957 "       #ifdef USENORMALMAPSCROLLBLEND\n"
958 "               vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
959 "               normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
960 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
961 "       #else\n"
962 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
963 "       #endif\n"
964 "       // FIXME temporary hack to detect the case that the reflection\n"
965 "       // gets blackened at edges due to leaving the area that contains actual\n"
966 "       // content.\n"
967 "       // Remove this 'ack once we have a better way to stop this thing from\n"
968 "       // 'appening.\n"
969 "       float f1 = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
970 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
971 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
972 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
973 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f1);\n"
974 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
975 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
976 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
977 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
978 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
979 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
980 "       gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
981 "       gl_FragColor.a = f1 + 0.5;\n"
982 "}\n"
983 "#endif\n"
984 "#else // !MODE_WATER\n"
985 "\n"
986 "\n"
987 "\n"
988 "\n"
989 "// common definitions between vertex shader and fragment shader:\n"
990 "\n"
991 "varying vec2 TexCoord;\n"
992 "#ifdef USEVERTEXTEXTUREBLEND\n"
993 "varying vec2 TexCoord2;\n"
994 "#endif\n"
995 "#ifdef USELIGHTMAP\n"
996 "varying vec2 TexCoordLightmap;\n"
997 "#endif\n"
998 "\n"
999 "#ifdef MODE_LIGHTSOURCE\n"
1000 "varying vec3 CubeVector;\n"
1001 "#endif\n"
1002 "\n"
1003 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1004 "varying vec3 LightVector;\n"
1005 "#endif\n"
1006 "\n"
1007 "#ifdef USEEYEVECTOR\n"
1008 "varying vec3 EyeVector;\n"
1009 "#endif\n"
1010 "#ifdef USEFOG\n"
1011 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1012 "#endif\n"
1013 "\n"
1014 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1015 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1016 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1017 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
1018 "#endif\n"
1019 "\n"
1020 "#ifdef USEREFLECTION\n"
1021 "varying vec4 ModelViewProjectionPosition;\n"
1022 "#endif\n"
1023 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1024 "uniform vec3 LightPosition;\n"
1025 "varying vec4 ModelViewPosition;\n"
1026 "#endif\n"
1027 "\n"
1028 "#ifdef MODE_LIGHTSOURCE\n"
1029 "uniform vec3 LightPosition;\n"
1030 "#endif\n"
1031 "uniform vec3 EyePosition;\n"
1032 "#ifdef MODE_LIGHTDIRECTION\n"
1033 "uniform vec3 LightDir;\n"
1034 "#endif\n"
1035 "uniform vec4 FogPlane;\n"
1036 "\n"
1037 "#ifdef USESHADOWMAPORTHO\n"
1038 "varying vec3 ShadowMapTC;\n"
1039 "#endif\n"
1040 "\n"
1041 "\n"
1042 "\n"
1043 "\n"
1044 "\n"
1045 "// 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"
1046 "\n"
1047 "// fragment shader specific:\n"
1048 "#ifdef FRAGMENT_SHADER\n"
1049 "\n"
1050 "uniform sampler2D Texture_Normal;\n"
1051 "uniform sampler2D Texture_Color;\n"
1052 "uniform sampler2D Texture_Gloss;\n"
1053 "#ifdef USEGLOW\n"
1054 "uniform sampler2D Texture_Glow;\n"
1055 "#endif\n"
1056 "#ifdef USEVERTEXTEXTUREBLEND\n"
1057 "uniform sampler2D Texture_SecondaryNormal;\n"
1058 "uniform sampler2D Texture_SecondaryColor;\n"
1059 "uniform sampler2D Texture_SecondaryGloss;\n"
1060 "#ifdef USEGLOW\n"
1061 "uniform sampler2D Texture_SecondaryGlow;\n"
1062 "#endif\n"
1063 "#endif\n"
1064 "#ifdef USECOLORMAPPING\n"
1065 "uniform sampler2D Texture_Pants;\n"
1066 "uniform sampler2D Texture_Shirt;\n"
1067 "#endif\n"
1068 "#ifdef USEFOG\n"
1069 "#ifdef USEFOGHEIGHTTEXTURE\n"
1070 "uniform sampler2D Texture_FogHeightTexture;\n"
1071 "#endif\n"
1072 "uniform sampler2D Texture_FogMask;\n"
1073 "#endif\n"
1074 "#ifdef USELIGHTMAP\n"
1075 "uniform sampler2D Texture_Lightmap;\n"
1076 "#endif\n"
1077 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1078 "uniform sampler2D Texture_Deluxemap;\n"
1079 "#endif\n"
1080 "#ifdef USEREFLECTION\n"
1081 "uniform sampler2D Texture_Reflection;\n"
1082 "#endif\n"
1083 "\n"
1084 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1085 "uniform sampler2D Texture_ScreenDepth;\n"
1086 "uniform sampler2D Texture_ScreenNormalMap;\n"
1087 "#endif\n"
1088 "#ifdef USEDEFERREDLIGHTMAP\n"
1089 "uniform sampler2D Texture_ScreenDiffuse;\n"
1090 "uniform sampler2D Texture_ScreenSpecular;\n"
1091 "#endif\n"
1092 "\n"
1093 "uniform myhalf3 Color_Pants;\n"
1094 "uniform myhalf3 Color_Shirt;\n"
1095 "uniform myhalf3 FogColor;\n"
1096 "\n"
1097 "#ifdef USEFOG\n"
1098 "uniform float FogRangeRecip;\n"
1099 "uniform float FogPlaneViewDist;\n"
1100 "uniform float FogHeightFade;\n"
1101 "vec3 FogVertex(vec3 surfacecolor)\n"
1102 "{\n"
1103 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1104 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1105 "       float fogfrac;\n"
1106 "#ifdef USEFOGHEIGHTTEXTURE\n"
1107 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1108 "       fogfrac = fogheightpixel.a;\n"
1109 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1110 "#else\n"
1111 "# ifdef USEFOGOUTSIDE\n"
1112 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1113 "# else\n"
1114 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1115 "# endif\n"
1116 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1117 "#endif\n"
1118 "}\n"
1119 "#endif\n"
1120 "\n"
1121 "#ifdef USEOFFSETMAPPING\n"
1122 "uniform float OffsetMapping_Scale;\n"
1123 "vec2 OffsetMapping(vec2 TexCoord)\n"
1124 "{\n"
1125 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1126 "       // 14 sample relief mapping: linear search and then binary search\n"
1127 "       // this basically steps forward a small amount repeatedly until it finds\n"
1128 "       // itself inside solid, then jitters forward and back using decreasing\n"
1129 "       // amounts to find the impact\n"
1130 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1131 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1132 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1133 "       vec3 RT = vec3(TexCoord, 1);\n"
1134 "       OffsetVector *= 0.1;\n"
1135 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1136 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1137 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1138 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1139 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1140 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1141 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1142 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1143 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1144 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1145 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1146 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1147 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1148 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1149 "       return RT.xy;\n"
1150 "#else\n"
1151 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1152 "       // this basically moves forward the full distance, and then backs up based\n"
1153 "       // on height of samples\n"
1154 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1155 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1156 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1157 "       TexCoord += OffsetVector;\n"
1158 "       OffsetVector *= 0.333;\n"
1159 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1160 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1161 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1162 "       return TexCoord;\n"
1163 "#endif\n"
1164 "}\n"
1165 "#endif // USEOFFSETMAPPING\n"
1166 "\n"
1167 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1168 "uniform sampler2D Texture_Attenuation;\n"
1169 "uniform samplerCube Texture_Cube;\n"
1170 "#endif\n"
1171 "\n"
1172 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1173 "\n"
1174 "#ifdef USESHADOWMAP2D\n"
1175 "# ifdef USESHADOWSAMPLER\n"
1176 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1177 "# else\n"
1178 "uniform sampler2D Texture_ShadowMap2D;\n"
1179 "# endif\n"
1180 "#endif\n"
1181 "\n"
1182 "#ifdef USESHADOWMAPVSDCT\n"
1183 "uniform samplerCube Texture_CubeProjection;\n"
1184 "#endif\n"
1185 "\n"
1186 "#if defined(USESHADOWMAP2D)\n"
1187 "uniform vec2 ShadowMap_TextureScale;\n"
1188 "uniform vec4 ShadowMap_Parameters;\n"
1189 "#endif\n"
1190 "\n"
1191 "#if defined(USESHADOWMAP2D)\n"
1192 "# ifdef USESHADOWMAPORTHO\n"
1193 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1194 "# else\n"
1195 "#  ifdef USESHADOWMAPVSDCT\n"
1196 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1197 "{\n"
1198 "       vec3 adir = abs(dir);\n"
1199 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1200 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1201 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1202 "}\n"
1203 "#  else\n"
1204 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1205 "{\n"
1206 "       vec3 adir = abs(dir);\n"
1207 "       float ma = adir.z;\n"
1208 "       vec4 proj = vec4(dir, 2.5);\n"
1209 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1210 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1211 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1212 "       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"
1213 "}\n"
1214 "#  endif\n"
1215 "# endif\n"
1216 "#endif // defined(USESHADOWMAP2D)\n"
1217 "\n"
1218 "# ifdef USESHADOWMAP2D\n"
1219 "float ShadowMapCompare(vec3 dir)\n"
1220 "{\n"
1221 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1222 "       float f;\n"
1223 "\n"
1224 "#  ifdef USESHADOWSAMPLER\n"
1225 "#    ifdef USESHADOWMAPPCF\n"
1226 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1227 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1228 "       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"
1229 "#    else\n"
1230 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1231 "#    endif\n"
1232 "#  else\n"
1233 "#    ifdef USESHADOWMAPPCF\n"
1234 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1235 "#      ifdef GL_ARB_texture_gather\n"
1236 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1237 "#      else\n"
1238 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1239 "#      endif\n"
1240 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1241 "#      if USESHADOWMAPPCF > 1\n"
1242 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1243 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1244 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1245 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1246 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1247 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1248 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1249 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1250 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1251 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1252 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1253 "       locols.yz += group2.ab;\n"
1254 "       hicols.yz += group8.rg;\n"
1255 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1256 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1257 "                               mix(locols, hicols, offset.y);\n"
1258 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1259 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1260 "       f = dot(cols, vec4(1.0/25.0));\n"
1261 "#      else\n"
1262 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1263 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1264 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1265 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1266 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1267 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1268 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1269 "#      endif\n"
1270 "#     else\n"
1271 "#      ifdef GL_EXT_gpu_shader4\n"
1272 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1273 "#      else\n"
1274 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1275 "#      endif\n"
1276 "#      if USESHADOWMAPPCF > 1\n"
1277 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1278 "       center *= ShadowMap_TextureScale;\n"
1279 "       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"
1280 "       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"
1281 "       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"
1282 "       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"
1283 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1284 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1285 "#      else\n"
1286 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1287 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1288 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1289 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1290 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1291 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1292 "#      endif\n"
1293 "#     endif\n"
1294 "#    else\n"
1295 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1296 "#    endif\n"
1297 "#  endif\n"
1298 "#  ifdef USESHADOWMAPORTHO\n"
1299 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1300 "#  else\n"
1301 "       return f;\n"
1302 "#  endif\n"
1303 "}\n"
1304 "# endif\n"
1305 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1306 "#endif // FRAGMENT_SHADER\n"
1307 "\n"
1308 "\n"
1309 "\n"
1310 "\n"
1311 "#ifdef MODE_DEFERREDGEOMETRY\n"
1312 "#ifdef VERTEX_SHADER\n"
1313 "uniform mat4 TexMatrix;\n"
1314 "#ifdef USEVERTEXTEXTUREBLEND\n"
1315 "uniform mat4 BackgroundTexMatrix;\n"
1316 "#endif\n"
1317 "uniform mat4 ModelViewMatrix;\n"
1318 "void main(void)\n"
1319 "{\n"
1320 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1321 "#ifdef USEVERTEXTEXTUREBLEND\n"
1322 "       gl_FrontColor = gl_Color;\n"
1323 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1324 "#endif\n"
1325 "\n"
1326 "       // transform unnormalized eye direction into tangent space\n"
1327 "#ifdef USEOFFSETMAPPING\n"
1328 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1329 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1330 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1331 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1332 "#endif\n"
1333 "\n"
1334 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1335 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1336 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1337 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1338 "}\n"
1339 "#endif // VERTEX_SHADER\n"
1340 "\n"
1341 "#ifdef FRAGMENT_SHADER\n"
1342 "void main(void)\n"
1343 "{\n"
1344 "#ifdef USEOFFSETMAPPING\n"
1345 "       // apply offsetmapping\n"
1346 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1347 "#define TexCoord TexCoordOffset\n"
1348 "#endif\n"
1349 "\n"
1350 "#ifdef USEALPHAKILL\n"
1351 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1352 "               discard;\n"
1353 "#endif\n"
1354 "\n"
1355 "#ifdef USEVERTEXTEXTUREBLEND\n"
1356 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1357 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1358 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1359 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1360 "#endif\n"
1361 "\n"
1362 "#ifdef USEVERTEXTEXTUREBLEND\n"
1363 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1364 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1365 "#else\n"
1366 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1367 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1368 "#endif\n"
1369 "\n"
1370 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1371 "}\n"
1372 "#endif // FRAGMENT_SHADER\n"
1373 "#else // !MODE_DEFERREDGEOMETRY\n"
1374 "\n"
1375 "\n"
1376 "\n"
1377 "\n"
1378 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1379 "#ifdef VERTEX_SHADER\n"
1380 "uniform mat4 ModelViewMatrix;\n"
1381 "void main(void)\n"
1382 "{\n"
1383 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1384 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1385 "}\n"
1386 "#endif // VERTEX_SHADER\n"
1387 "\n"
1388 "#ifdef FRAGMENT_SHADER\n"
1389 "uniform mat4 ViewToLight;\n"
1390 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1391 "uniform vec2 ScreenToDepth;\n"
1392 "uniform myhalf3 DeferredColor_Ambient;\n"
1393 "uniform myhalf3 DeferredColor_Diffuse;\n"
1394 "#ifdef USESPECULAR\n"
1395 "uniform myhalf3 DeferredColor_Specular;\n"
1396 "uniform myhalf SpecularPower;\n"
1397 "#endif\n"
1398 "uniform myhalf2 PixelToScreenTexCoord;\n"
1399 "void main(void)\n"
1400 "{\n"
1401 "       // calculate viewspace pixel position\n"
1402 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1403 "       vec3 position;\n"
1404 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1405 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1406 "       // decode viewspace pixel normal\n"
1407 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1408 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1409 "       // surfacenormal = pixel normal in viewspace\n"
1410 "       // LightVector = pixel to light in viewspace\n"
1411 "       // CubeVector = position in lightspace\n"
1412 "       // eyevector = pixel to view in viewspace\n"
1413 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1414 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1415 "#ifdef USEDIFFUSE\n"
1416 "       // calculate diffuse shading\n"
1417 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1418 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1419 "#endif\n"
1420 "#ifdef USESPECULAR\n"
1421 "       // calculate directional shading\n"
1422 "       vec3 eyevector = position * -1.0;\n"
1423 "#  ifdef USEEXACTSPECULARMATH\n"
1424 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1425 "#  else\n"
1426 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1427 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1428 "#  endif\n"
1429 "#endif\n"
1430 "\n"
1431 "#if defined(USESHADOWMAP2D)\n"
1432 "       fade *= ShadowMapCompare(CubeVector);\n"
1433 "#endif\n"
1434 "\n"
1435 "#ifdef USEDIFFUSE\n"
1436 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1437 "#else\n"
1438 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1439 "#endif\n"
1440 "#ifdef USESPECULAR\n"
1441 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1442 "#else\n"
1443 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1444 "#endif\n"
1445 "\n"
1446 "# ifdef USECUBEFILTER\n"
1447 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1448 "       gl_FragData[0].rgb *= cubecolor;\n"
1449 "       gl_FragData[1].rgb *= cubecolor;\n"
1450 "# endif\n"
1451 "}\n"
1452 "#endif // FRAGMENT_SHADER\n"
1453 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1454 "\n"
1455 "\n"
1456 "\n"
1457 "\n"
1458 "#ifdef VERTEX_SHADER\n"
1459 "uniform mat4 TexMatrix;\n"
1460 "#ifdef USEVERTEXTEXTUREBLEND\n"
1461 "uniform mat4 BackgroundTexMatrix;\n"
1462 "#endif\n"
1463 "#ifdef MODE_LIGHTSOURCE\n"
1464 "uniform mat4 ModelToLight;\n"
1465 "#endif\n"
1466 "#ifdef USESHADOWMAPORTHO\n"
1467 "uniform mat4 ShadowMapMatrix;\n"
1468 "#endif\n"
1469 "void main(void)\n"
1470 "{\n"
1471 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1472 "       gl_FrontColor = gl_Color;\n"
1473 "#endif\n"
1474 "       // copy the surface texcoord\n"
1475 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1476 "#ifdef USEVERTEXTEXTUREBLEND\n"
1477 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1478 "#endif\n"
1479 "#ifdef USELIGHTMAP\n"
1480 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1481 "#endif\n"
1482 "\n"
1483 "#ifdef MODE_LIGHTSOURCE\n"
1484 "       // transform vertex position into light attenuation/cubemap space\n"
1485 "       // (-1 to +1 across the light box)\n"
1486 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1487 "\n"
1488 "# ifdef USEDIFFUSE\n"
1489 "       // transform unnormalized light direction into tangent space\n"
1490 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1491 "       //  normalize it per pixel)\n"
1492 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1493 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1494 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1495 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1496 "# endif\n"
1497 "#endif\n"
1498 "\n"
1499 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1500 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1501 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1502 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1503 "#endif\n"
1504 "\n"
1505 "       // transform unnormalized eye direction into tangent space\n"
1506 "#ifdef USEEYEVECTOR\n"
1507 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1508 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1509 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1510 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1511 "#endif\n"
1512 "\n"
1513 "#ifdef USEFOG\n"
1514 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1515 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1516 "#endif\n"
1517 "\n"
1518 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1519 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1520 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1521 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1522 "#endif\n"
1523 "\n"
1524 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1525 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1526 "\n"
1527 "#ifdef USESHADOWMAPORTHO\n"
1528 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1529 "#endif\n"
1530 "\n"
1531 "#ifdef USEREFLECTION\n"
1532 "       ModelViewProjectionPosition = gl_Position;\n"
1533 "#endif\n"
1534 "}\n"
1535 "#endif // VERTEX_SHADER\n"
1536 "\n"
1537 "\n"
1538 "\n"
1539 "\n"
1540 "#ifdef FRAGMENT_SHADER\n"
1541 "#ifdef USEDEFERREDLIGHTMAP\n"
1542 "uniform myhalf2 PixelToScreenTexCoord;\n"
1543 "uniform myhalf3 DeferredMod_Diffuse;\n"
1544 "uniform myhalf3 DeferredMod_Specular;\n"
1545 "#endif\n"
1546 "uniform myhalf3 Color_Ambient;\n"
1547 "uniform myhalf3 Color_Diffuse;\n"
1548 "uniform myhalf3 Color_Specular;\n"
1549 "uniform myhalf SpecularPower;\n"
1550 "#ifdef USEGLOW\n"
1551 "uniform myhalf3 Color_Glow;\n"
1552 "#endif\n"
1553 "uniform myhalf Alpha;\n"
1554 "#ifdef USEREFLECTION\n"
1555 "uniform vec4 DistortScaleRefractReflect;\n"
1556 "uniform vec4 ScreenScaleRefractReflect;\n"
1557 "uniform vec4 ScreenCenterRefractReflect;\n"
1558 "uniform myhalf4 ReflectColor;\n"
1559 "#endif\n"
1560 "#ifdef USEREFLECTCUBE\n"
1561 "uniform mat4 ModelToReflectCube;\n"
1562 "uniform sampler2D Texture_ReflectMask;\n"
1563 "uniform samplerCube Texture_ReflectCube;\n"
1564 "#endif\n"
1565 "#ifdef MODE_LIGHTDIRECTION\n"
1566 "uniform myhalf3 LightColor;\n"
1567 "#endif\n"
1568 "#ifdef MODE_LIGHTSOURCE\n"
1569 "uniform myhalf3 LightColor;\n"
1570 "#endif\n"
1571 "void main(void)\n"
1572 "{\n"
1573 "#ifdef USEOFFSETMAPPING\n"
1574 "       // apply offsetmapping\n"
1575 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1576 "#define TexCoord TexCoordOffset\n"
1577 "#endif\n"
1578 "\n"
1579 "       // combine the diffuse textures (base, pants, shirt)\n"
1580 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1581 "#ifdef USEALPHAKILL\n"
1582 "       if (color.a < 0.5)\n"
1583 "               discard;\n"
1584 "#endif\n"
1585 "       color.a *= Alpha;\n"
1586 "#ifdef USECOLORMAPPING\n"
1587 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1588 "#endif\n"
1589 "#ifdef USEVERTEXTEXTUREBLEND\n"
1590 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1591 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1592 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1593 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1594 "       color.a = 1.0;\n"
1595 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1596 "#endif\n"
1597 "\n"
1598 "       // get the surface normal\n"
1599 "#ifdef USEVERTEXTEXTUREBLEND\n"
1600 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1601 "#else\n"
1602 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1603 "#endif\n"
1604 "\n"
1605 "       // get the material colors\n"
1606 "       myhalf3 diffusetex = color.rgb;\n"
1607 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1608 "# ifdef USEVERTEXTEXTUREBLEND\n"
1609 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1610 "# else\n"
1611 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1612 "# endif\n"
1613 "#endif\n"
1614 "\n"
1615 "#ifdef USEREFLECTCUBE\n"
1616 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1617 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1618 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1619 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1620 "#endif\n"
1621 "\n"
1622 "\n"
1623 "\n"
1624 "\n"
1625 "#ifdef MODE_LIGHTSOURCE\n"
1626 "       // light source\n"
1627 "#ifdef USEDIFFUSE\n"
1628 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1629 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1630 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1631 "#ifdef USESPECULAR\n"
1632 "#ifdef USEEXACTSPECULARMATH\n"
1633 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1634 "#else\n"
1635 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1636 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1637 "#endif\n"
1638 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1639 "#endif\n"
1640 "#else\n"
1641 "       color.rgb = diffusetex * Color_Ambient;\n"
1642 "#endif\n"
1643 "       color.rgb *= LightColor;\n"
1644 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1645 "#if defined(USESHADOWMAP2D)\n"
1646 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1647 "#endif\n"
1648 "# ifdef USECUBEFILTER\n"
1649 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1650 "# endif\n"
1651 "#endif // MODE_LIGHTSOURCE\n"
1652 "\n"
1653 "\n"
1654 "\n"
1655 "\n"
1656 "#ifdef MODE_LIGHTDIRECTION\n"
1657 "#define SHADING\n"
1658 "#ifdef USEDIFFUSE\n"
1659 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1660 "#endif\n"
1661 "#define lightcolor LightColor\n"
1662 "#endif // MODE_LIGHTDIRECTION\n"
1663 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1664 "#define SHADING\n"
1665 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1666 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1667 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1668 "       // convert modelspace light vector to tangentspace\n"
1669 "       myhalf3 lightnormal;\n"
1670 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1671 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1672 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1673 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1674 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1675 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1676 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1677 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1678 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1679 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1680 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1681 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1682 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1683 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1684 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1685 "#define SHADING\n"
1686 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1687 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1688 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1689 "#endif\n"
1690 "\n"
1691 "\n"
1692 "\n"
1693 "\n"
1694 "#ifdef MODE_FAKELIGHT\n"
1695 "#define SHADING\n"
1696 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1697 "myhalf3 lightcolor = myhalf3(1.0);\n"
1698 "#endif // MODE_FAKELIGHT\n"
1699 "\n"
1700 "\n"
1701 "\n"
1702 "\n"
1703 "#ifdef MODE_LIGHTMAP\n"
1704 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1705 "#endif // MODE_LIGHTMAP\n"
1706 "#ifdef MODE_VERTEXCOLOR\n"
1707 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1708 "#endif // MODE_VERTEXCOLOR\n"
1709 "#ifdef MODE_FLATCOLOR\n"
1710 "       color.rgb = diffusetex * Color_Ambient;\n"
1711 "#endif // MODE_FLATCOLOR\n"
1712 "\n"
1713 "\n"
1714 "\n"
1715 "\n"
1716 "#ifdef SHADING\n"
1717 "# ifdef USEDIFFUSE\n"
1718 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1719 "#  ifdef USESPECULAR\n"
1720 "#   ifdef USEEXACTSPECULARMATH\n"
1721 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1722 "#   else\n"
1723 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1724 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1725 "#   endif\n"
1726 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1727 "#  else\n"
1728 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1729 "#  endif\n"
1730 "# else\n"
1731 "       color.rgb = diffusetex * Color_Ambient;\n"
1732 "# endif\n"
1733 "#endif\n"
1734 "\n"
1735 "#ifdef USESHADOWMAPORTHO\n"
1736 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1737 "#endif\n"
1738 "\n"
1739 "#ifdef USEDEFERREDLIGHTMAP\n"
1740 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1741 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1742 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1743 "#endif\n"
1744 "\n"
1745 "#ifdef USEGLOW\n"
1746 "#ifdef USEVERTEXTEXTUREBLEND\n"
1747 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1748 "#else\n"
1749 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1750 "#endif\n"
1751 "#endif\n"
1752 "\n"
1753 "#ifdef USEFOG\n"
1754 "       color.rgb = FogVertex(color.rgb);\n"
1755 "#endif\n"
1756 "\n"
1757 "       // 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"
1758 "#ifdef USEREFLECTION\n"
1759 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1760 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1761 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1762 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1763 "       // FIXME temporary hack to detect the case that the reflection\n"
1764 "       // gets blackened at edges due to leaving the area that contains actual\n"
1765 "       // content.\n"
1766 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1767 "       // 'appening.\n"
1768 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1769 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1770 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1771 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1772 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1773 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1774 "#endif\n"
1775 "\n"
1776 "       gl_FragColor = vec4(color);\n"
1777 "}\n"
1778 "#endif // FRAGMENT_SHADER\n"
1779 "\n"
1780 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1781 "#endif // !MODE_DEFERREDGEOMETRY\n"
1782 "#endif // !MODE_WATER\n"
1783 "#endif // !MODE_REFRACTION\n"
1784 "#endif // !MODE_BLOOMBLUR\n"
1785 "#endif // !MODE_GENERIC\n"
1786 "#endif // !MODE_POSTPROCESS\n"
1787 "#endif // !MODE_SHOWDEPTH\n"
1788 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1789 ;
1790
1791 /*
1792 =========================================================================================================================================================
1793
1794
1795
1796 =========================================================================================================================================================
1797
1798
1799
1800 =========================================================================================================================================================
1801
1802
1803
1804 =========================================================================================================================================================
1805
1806
1807
1808 =========================================================================================================================================================
1809
1810
1811
1812 =========================================================================================================================================================
1813
1814
1815
1816 =========================================================================================================================================================
1817 */
1818
1819 const char *builtincgshaderstring =
1820 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1821 "// written by Forest 'LordHavoc' Hale\n"
1822 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1823 "\n"
1824 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1825 "#if defined(USEREFLECTION)\n"
1826 "#undef USESHADOWMAPORTHO\n"
1827 "#endif\n"
1828 "\n"
1829 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1830 "# define USEFOG\n"
1831 "#endif\n"
1832 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1833 "#define USELIGHTMAP\n"
1834 "#endif\n"
1835 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1836 "#define USEEYEVECTOR\n"
1837 "#endif\n"
1838 "\n"
1839 "#ifdef FRAGMENT_SHADER\n"
1840 "#ifdef HLSL\n"
1841 "//#undef USESHADOWMAPPCF\n"
1842 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1843 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1844 "#else\n"
1845 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1846 "#endif\n"
1847 "#endif\n"
1848 "\n"
1849 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1850 "#ifdef VERTEX_SHADER\n"
1851 "void main\n"
1852 "(\n"
1853 "float4 gl_Vertex : POSITION,\n"
1854 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1855 "out float4 gl_Position : POSITION,\n"
1856 "out float Depth : TEXCOORD0\n"
1857 ")\n"
1858 "{\n"
1859 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1860 "       Depth = gl_Position.z;\n"
1861 "}\n"
1862 "#endif\n"
1863 "\n"
1864 "#ifdef FRAGMENT_SHADER\n"
1865 "void main\n"
1866 "(\n"
1867 "float Depth : TEXCOORD0,\n"
1868 "out float4 gl_FragColor : COLOR\n"
1869 ")\n"
1870 "{\n"
1871 "//     float3 temp = float3(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0));\n"
1872 "       float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1873 "       temp.yz -= floor(temp.yz);\n"
1874 "       gl_FragColor = temp;\n"
1875 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1876 "}\n"
1877 "#endif\n"
1878 "#else // !MODE_DEPTH_ORSHADOW\n"
1879 "\n"
1880 "\n"
1881 "\n"
1882 "\n"
1883 "#ifdef MODE_SHOWDEPTH\n"
1884 "#ifdef VERTEX_SHADER\n"
1885 "void main\n"
1886 "(\n"
1887 "float4 gl_Vertex : POSITION,\n"
1888 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1889 "out float4 gl_Position : POSITION,\n"
1890 "out float4 gl_FrontColor : COLOR0\n"
1891 ")\n"
1892 "{\n"
1893 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1894 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1895 "}\n"
1896 "#endif\n"
1897 "\n"
1898 "#ifdef FRAGMENT_SHADER\n"
1899 "void main\n"
1900 "(\n"
1901 "float4 gl_FrontColor : COLOR0,\n"
1902 "out float4 gl_FragColor : COLOR\n"
1903 ")\n"
1904 "{\n"
1905 "       gl_FragColor = gl_FrontColor;\n"
1906 "}\n"
1907 "#endif\n"
1908 "#else // !MODE_SHOWDEPTH\n"
1909 "\n"
1910 "\n"
1911 "\n"
1912 "\n"
1913 "#ifdef MODE_POSTPROCESS\n"
1914 "\n"
1915 "#ifdef VERTEX_SHADER\n"
1916 "void main\n"
1917 "(\n"
1918 "float4 gl_Vertex : POSITION,\n"
1919 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1920 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1921 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1922 "out float4 gl_Position : POSITION,\n"
1923 "out float2 TexCoord1 : TEXCOORD0,\n"
1924 "out float2 TexCoord2 : TEXCOORD1\n"
1925 ")\n"
1926 "{\n"
1927 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1928 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1929 "#ifdef USEBLOOM\n"
1930 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1931 "#endif\n"
1932 "}\n"
1933 "#endif\n"
1934 "\n"
1935 "#ifdef FRAGMENT_SHADER\n"
1936 "void main\n"
1937 "(\n"
1938 "float2 TexCoord1 : TEXCOORD0,\n"
1939 "float2 TexCoord2 : TEXCOORD1,\n"
1940 "uniform sampler Texture_First : register(s0),\n"
1941 "#ifdef USEBLOOM\n"
1942 "uniform sampler Texture_Second : register(s1),\n"
1943 "#endif\n"
1944 "#ifdef USEGAMMARAMPS\n"
1945 "uniform sampler Texture_GammaRamps : register(s2),\n"
1946 "#endif\n"
1947 "#ifdef USESATURATION\n"
1948 "uniform float Saturation : register(c30),\n"
1949 "#endif\n"
1950 "#ifdef USEVIEWTINT\n"
1951 "uniform float4 ViewTintColor : register(c41),\n"
1952 "#endif\n"
1953 "uniform float4 UserVec1 : register(c37),\n"
1954 "uniform float4 UserVec2 : register(c38),\n"
1955 "uniform float4 UserVec3 : register(c39),\n"
1956 "uniform float4 UserVec4 : register(c40),\n"
1957 "uniform float ClientTime : register(c2),\n"
1958 "uniform float2 PixelSize : register(c25),\n"
1959 "uniform float4 BloomColorSubtract : register(c43),\n"
1960 "out float4 gl_FragColor : COLOR\n"
1961 ")\n"
1962 "{\n"
1963 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1964 "#ifdef USEBLOOM\n"
1965 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1966 "#endif\n"
1967 "#ifdef USEVIEWTINT\n"
1968 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1969 "#endif\n"
1970 "\n"
1971 "#ifdef USEPOSTPROCESSING\n"
1972 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1973 "// 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"
1974 "       float sobel = 1.0;\n"
1975 "       // float2 ts = textureSize(Texture_First, 0);\n"
1976 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
1977 "       float2 px = PixelSize;\n"
1978 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1979 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
1980 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1981 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1982 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
1983 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1984 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1985 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
1986 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1987 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1988 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
1989 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1990 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
1991 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
1992 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
1993 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
1994 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
1995 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
1996 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
1997 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
1998 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
1999 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2000 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2001 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2002 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2003 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2004 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2005 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2006 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2007 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2008 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2009 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2010 "#endif\n"
2011 "\n"
2012 "#ifdef USESATURATION\n"
2013 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2014 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2015 "       // 'vampire sight' effect, wheres red is compensated\n"
2016 "       #ifdef SATURATION_REDCOMPENSATE\n"
2017 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2018 "               gl_FragColor.rgb = mix(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2019 "               gl_FragColor.r += r;\n"
2020 "       #else\n"
2021 "               // normal desaturation\n"
2022 "               //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2023 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2024 "       #endif\n"
2025 "#endif\n"
2026 "\n"
2027 "#ifdef USEGAMMARAMPS\n"
2028 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2029 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2030 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2031 "#endif\n"
2032 "}\n"
2033 "#endif\n"
2034 "#else // !MODE_POSTPROCESS\n"
2035 "\n"
2036 "\n"
2037 "\n"
2038 "\n"
2039 "#ifdef MODE_GENERIC\n"
2040 "#ifdef VERTEX_SHADER\n"
2041 "void main\n"
2042 "(\n"
2043 "float4 gl_Vertex : POSITION,\n"
2044 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2045 "float4 gl_Color : COLOR0,\n"
2046 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2047 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2048 "out float4 gl_Position : POSITION,\n"
2049 "#ifdef USEDIFFUSE\n"
2050 "out float2 TexCoord1 : TEXCOORD0,\n"
2051 "#endif\n"
2052 "#ifdef USESPECULAR\n"
2053 "out float2 TexCoord2 : TEXCOORD1,\n"
2054 "#endif\n"
2055 "out float4 gl_FrontColor : COLOR\n"
2056 ")\n"
2057 "{\n"
2058 "#ifdef HLSL\n"
2059 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2060 "#else\n"
2061 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2062 "#endif\n"
2063 "#ifdef USEDIFFUSE\n"
2064 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2065 "#endif\n"
2066 "#ifdef USESPECULAR\n"
2067 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2068 "#endif\n"
2069 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2070 "}\n"
2071 "#endif\n"
2072 "\n"
2073 "#ifdef FRAGMENT_SHADER\n"
2074 "\n"
2075 "void main\n"
2076 "(\n"
2077 "float4 gl_FrontColor : COLOR0,\n"
2078 "float2 TexCoord1 : TEXCOORD0,\n"
2079 "float2 TexCoord2 : TEXCOORD1,\n"
2080 "#ifdef USEDIFFUSE\n"
2081 "uniform sampler Texture_First : register(s0),\n"
2082 "#endif\n"
2083 "#ifdef USESPECULAR\n"
2084 "uniform sampler Texture_Second : register(s1),\n"
2085 "#endif\n"
2086 "out float4 gl_FragColor : COLOR\n"
2087 ")\n"
2088 "{\n"
2089 "       gl_FragColor = gl_FrontColor;\n"
2090 "#ifdef USEDIFFUSE\n"
2091 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2092 "#endif\n"
2093 "\n"
2094 "#ifdef USESPECULAR\n"
2095 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2096 "# ifdef USECOLORMAPPING\n"
2097 "       gl_FragColor *= tex2;\n"
2098 "# endif\n"
2099 "# ifdef USEGLOW\n"
2100 "       gl_FragColor += tex2;\n"
2101 "# endif\n"
2102 "# ifdef USEVERTEXTEXTUREBLEND\n"
2103 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2104 "# endif\n"
2105 "#endif\n"
2106 "}\n"
2107 "#endif\n"
2108 "#else // !MODE_GENERIC\n"
2109 "\n"
2110 "\n"
2111 "\n"
2112 "\n"
2113 "#ifdef MODE_BLOOMBLUR\n"
2114 "#ifdef VERTEX_SHADER\n"
2115 "void main\n"
2116 "(\n"
2117 "float4 gl_Vertex : POSITION,\n"
2118 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2119 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2120 "out float4 gl_Position : POSITION,\n"
2121 "out float2 TexCoord : TEXCOORD0\n"
2122 ")\n"
2123 "{\n"
2124 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2125 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2126 "}\n"
2127 "#endif\n"
2128 "\n"
2129 "#ifdef FRAGMENT_SHADER\n"
2130 "\n"
2131 "void main\n"
2132 "(\n"
2133 "float2 TexCoord : TEXCOORD0,\n"
2134 "uniform sampler Texture_First : register(s0),\n"
2135 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2136 "out float4 gl_FragColor : COLOR\n"
2137 ")\n"
2138 "{\n"
2139 "       int i;\n"
2140 "       float2 tc = TexCoord;\n"
2141 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2142 "       tc += BloomBlur_Parameters.xy;\n"
2143 "       for (i = 1;i < SAMPLES;i++)\n"
2144 "       {\n"
2145 "               color += tex2D(Texture_First, tc).rgb;\n"
2146 "               tc += BloomBlur_Parameters.xy;\n"
2147 "       }\n"
2148 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2149 "}\n"
2150 "#endif\n"
2151 "#else // !MODE_BLOOMBLUR\n"
2152 "#ifdef MODE_REFRACTION\n"
2153 "#ifdef VERTEX_SHADER\n"
2154 "void main\n"
2155 "(\n"
2156 "float4 gl_Vertex : POSITION,\n"
2157 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2158 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2159 "uniform float4x4 TexMatrix : register(c0),\n"
2160 "uniform float3 EyePosition : register(c24),\n"
2161 "out float4 gl_Position : POSITION,\n"
2162 "out float2 TexCoord : TEXCOORD0,\n"
2163 "out float3 EyeVector : TEXCOORD1,\n"
2164 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2165 ")\n"
2166 "{\n"
2167 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2168 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2169 "       ModelViewProjectionPosition = gl_Position;\n"
2170 "}\n"
2171 "#endif\n"
2172 "\n"
2173 "#ifdef FRAGMENT_SHADER\n"
2174 "void main\n"
2175 "(\n"
2176 "float2 TexCoord : TEXCOORD0,\n"
2177 "float3 EyeVector : TEXCOORD1,\n"
2178 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2179 "uniform sampler Texture_Normal : register(s0),\n"
2180 "uniform sampler Texture_Refraction : register(s3),\n"
2181 "uniform sampler Texture_Reflection : register(s7),\n"
2182 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2183 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2184 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2185 "uniform float4 RefractColor : register(c29),\n"
2186 "out float4 gl_FragColor : COLOR\n"
2187 ")\n"
2188 "{\n"
2189 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2190 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2191 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2192 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.xy;\n"
2193 "       // FIXME temporary hack to detect the case that the reflection\n"
2194 "       // gets blackened at edges due to leaving the area that contains actual\n"
2195 "       // content.\n"
2196 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2197 "       // 'appening.\n"
2198 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2199 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2200 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2201 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2202 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2203 "       gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2204 "}\n"
2205 "#endif\n"
2206 "#else // !MODE_REFRACTION\n"
2207 "\n"
2208 "\n"
2209 "\n"
2210 "\n"
2211 "#ifdef MODE_WATER\n"
2212 "#ifdef VERTEX_SHADER\n"
2213 "\n"
2214 "void main\n"
2215 "(\n"
2216 "float4 gl_Vertex : POSITION,\n"
2217 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2218 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2219 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2220 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2221 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2222 "uniform float4x4 TexMatrix : register(c0),\n"
2223 "uniform float3 EyePosition : register(c24),\n"
2224 "out float4 gl_Position : POSITION,\n"
2225 "out float2 TexCoord : TEXCOORD0,\n"
2226 "out float3 EyeVector : TEXCOORD1,\n"
2227 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2228 ")\n"
2229 "{\n"
2230 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2231 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2232 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2233 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2234 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2235 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2236 "       ModelViewProjectionPosition = gl_Position;\n"
2237 "}\n"
2238 "#endif\n"
2239 "\n"
2240 "#ifdef FRAGMENT_SHADER\n"
2241 "void main\n"
2242 "(\n"
2243 "float2 TexCoord : TEXCOORD0,\n"
2244 "float3 EyeVector : TEXCOORD1,\n"
2245 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2246 "uniform sampler Texture_Normal : register(s0),\n"
2247 "uniform sampler Texture_Refraction : register(s3),\n"
2248 "uniform sampler Texture_Reflection : register(s7),\n"
2249 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2250 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2251 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2252 "uniform float4 RefractColor : register(c29),\n"
2253 "uniform float4 ReflectColor : register(c26),\n"
2254 "uniform float ReflectFactor : register(c27),\n"
2255 "uniform float ReflectOffset : register(c28),\n"
2256 "out float4 gl_FragColor : COLOR\n"
2257 ")\n"
2258 "{\n"
2259 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2260 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2261 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2262 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2263 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2264 "       // FIXME temporary hack to detect the case that the reflection\n"
2265 "       // gets blackened at edges due to leaving the area that contains actual\n"
2266 "       // content.\n"
2267 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2268 "       // 'appening.\n"
2269 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2270 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2271 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2272 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2273 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2274 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2275 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2276 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2277 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2278 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2279 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2280 "       gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2281 "}\n"
2282 "#endif\n"
2283 "#else // !MODE_WATER\n"
2284 "\n"
2285 "\n"
2286 "\n"
2287 "\n"
2288 "// 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"
2289 "\n"
2290 "// fragment shader specific:\n"
2291 "#ifdef FRAGMENT_SHADER\n"
2292 "\n"
2293 "#ifdef USEFOG\n"
2294 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2295 "{\n"
2296 "       float fogfrac;\n"
2297 "#ifdef USEFOGHEIGHTTEXTURE\n"
2298 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2299 "       fogfrac = fogheightpixel.a;\n"
2300 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2301 "#else\n"
2302 "# ifdef USEFOGOUTSIDE\n"
2303 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2304 "# else\n"
2305 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2306 "# endif\n"
2307 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2308 "#endif\n"
2309 "}\n"
2310 "#endif\n"
2311 "\n"
2312 "#ifdef USEOFFSETMAPPING\n"
2313 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2314 "{\n"
2315 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2316 "       // 14 sample relief mapping: linear search and then binary search\n"
2317 "       // this basically steps forward a small amount repeatedly until it finds\n"
2318 "       // itself inside solid, then jitters forward and back using decreasing\n"
2319 "       // amounts to find the impact\n"
2320 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2321 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2322 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2323 "       float3 RT = float3(TexCoord, 1);\n"
2324 "       OffsetVector *= 0.1;\n"
2325 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2326 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2327 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2328 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2329 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2330 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2331 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2332 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2333 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2334 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2335 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2336 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2337 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2338 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2339 "       return RT.xy;\n"
2340 "#else\n"
2341 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2342 "       // this basically moves forward the full distance, and then backs up based\n"
2343 "       // on height of samples\n"
2344 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2345 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2346 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2347 "       TexCoord += OffsetVector;\n"
2348 "       OffsetVector *= 0.333;\n"
2349 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2350 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2351 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2352 "       return TexCoord;\n"
2353 "#endif\n"
2354 "}\n"
2355 "#endif // USEOFFSETMAPPING\n"
2356 "\n"
2357 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2358 "#if defined(USESHADOWMAP2D)\n"
2359 "# ifdef USESHADOWMAPORTHO\n"
2360 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2361 "# else\n"
2362 "#  ifdef USESHADOWMAPVSDCT\n"
2363 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2364 "{\n"
2365 "       float3 adir = abs(dir);\n"
2366 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2367 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2368 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2369 "}\n"
2370 "#  else\n"
2371 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2372 "{\n"
2373 "       float3 adir = abs(dir);\n"
2374 "       float ma = adir.z;\n"
2375 "       float4 proj = float4(dir, 2.5);\n"
2376 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2377 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2378 "#ifdef HLSL\n"
2379 "       return float3(proj.xy * ShadowMap_Parameters.x / ma + float2(0.5,0.5) + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, ma + 64 * ShadowMap_Parameters.w);\n"
2380 "#else\n"
2381 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2382 "       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"
2383 "#endif\n"
2384 "}\n"
2385 "#  endif\n"
2386 "# endif\n"
2387 "#endif // defined(USESHADOWMAP2D)\n"
2388 "\n"
2389 "# ifdef USESHADOWMAP2D\n"
2390 "#ifdef USESHADOWMAPVSDCT\n"
2391 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2392 "#else\n"
2393 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2394 "#endif\n"
2395 "{\n"
2396 "#ifdef USESHADOWMAPVSDCT\n"
2397 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2398 "#else\n"
2399 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2400 "#endif\n"
2401 "       float f;\n"
2402 "\n"
2403 "#  ifdef USESHADOWSAMPLER\n"
2404 "#    ifdef USESHADOWMAPPCF\n"
2405 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2406 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2407 "       f = dot(float4(0.25,0.25,0.25,0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2408 "#    else\n"
2409 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2410 "#    endif\n"
2411 "#  else\n"
2412 "#    ifdef USESHADOWMAPPCF\n"
2413 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2414 "#      ifdef GL_ARB_texture_gather\n"
2415 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2416 "#      else\n"
2417 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2418 "#      endif\n"
2419 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2420 "#      if USESHADOWMAPPCF > 1\n"
2421 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2422 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2423 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2424 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2425 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2426 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2427 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2428 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2429 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2430 "       float4 locols = float4(group1.ab, group3.ab);\n"
2431 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2432 "       locols.yz += group2.ab;\n"
2433 "       hicols.yz += group8.rg;\n"
2434 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2435 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2436 "                               lerp(locols, hicols, offset.y);\n"
2437 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2438 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2439 "       f = dot(cols, float4(1.0/25.0));\n"
2440 "#      else\n"
2441 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2442 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2443 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2444 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2445 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2446 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2447 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2448 "#      endif\n"
2449 "#     else\n"
2450 "#      ifdef GL_EXT_gpu_shader4\n"
2451 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2452 "#      else\n"
2453 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2454 "#      endif\n"
2455 "#      if USESHADOWMAPPCF > 1\n"
2456 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2457 "       center *= ShadowMap_TextureScale;\n"
2458 "       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"
2459 "       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"
2460 "       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"
2461 "       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"
2462 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2463 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2464 "#      else\n"
2465 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2466 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2467 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2468 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2469 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2470 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2471 "#      endif\n"
2472 "#     endif\n"
2473 "#    else\n"
2474 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2475 "#    endif\n"
2476 "#  endif\n"
2477 "#  ifdef USESHADOWMAPORTHO\n"
2478 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2479 "#  else\n"
2480 "       return f;\n"
2481 "#  endif\n"
2482 "}\n"
2483 "# endif\n"
2484 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2485 "#endif // FRAGMENT_SHADER\n"
2486 "\n"
2487 "\n"
2488 "\n"
2489 "\n"
2490 "#ifdef MODE_DEFERREDGEOMETRY\n"
2491 "#ifdef VERTEX_SHADER\n"
2492 "void main\n"
2493 "(\n"
2494 "float4 gl_Vertex : POSITION,\n"
2495 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2496 "#ifdef USEVERTEXTEXTUREBLEND\n"
2497 "float4 gl_Color : COLOR0,\n"
2498 "#endif\n"
2499 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2500 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2501 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2502 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2503 "uniform float4x4 TexMatrix : register(c0),\n"
2504 "#ifdef USEVERTEXTEXTUREBLEND\n"
2505 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2506 "#endif\n"
2507 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2508 "#ifdef USEOFFSETMAPPING\n"
2509 "uniform float3 EyePosition : register(c24),\n"
2510 "#endif\n"
2511 "out float4 gl_Position : POSITION,\n"
2512 "#ifdef USEVERTEXTEXTUREBLEND\n"
2513 "out float4 gl_FrontColor : COLOR,\n"
2514 "#endif\n"
2515 "out float4 TexCoordBoth : TEXCOORD0,\n"
2516 "#ifdef USEOFFSETMAPPING\n"
2517 "out float3 EyeVector : TEXCOORD2,\n"
2518 "#endif\n"
2519 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2520 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2521 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2522 ")\n"
2523 "{\n"
2524 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2525 "#ifdef USEVERTEXTEXTUREBLEND\n"
2526 "#ifdef HLSL\n"
2527 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2528 "#else\n"
2529 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2530 "#endif\n"
2531 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2532 "#endif\n"
2533 "\n"
2534 "       // transform unnormalized eye direction into tangent space\n"
2535 "#ifdef USEOFFSETMAPPING\n"
2536 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2537 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2538 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2539 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2540 "#endif\n"
2541 "\n"
2542 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2543 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2544 "       VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2545 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2546 "       VectorR.w = gl_Position.z;\n"
2547 "}\n"
2548 "#endif // VERTEX_SHADER\n"
2549 "\n"
2550 "#ifdef FRAGMENT_SHADER\n"
2551 "void main\n"
2552 "(\n"
2553 "float4 TexCoordBoth : TEXCOORD0,\n"
2554 "float3 EyeVector : TEXCOORD2,\n"
2555 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2556 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2557 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2558 "uniform sampler Texture_Normal : register(s0),\n"
2559 "#ifdef USEALPHAKILL\n"
2560 "uniform sampler Texture_Color : register(s1),\n"
2561 "#endif\n"
2562 "uniform sampler Texture_Gloss : register(s2),\n"
2563 "#ifdef USEVERTEXTEXTUREBLEND\n"
2564 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2565 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2566 "#endif\n"
2567 "#ifdef USEOFFSETMAPPING\n"
2568 "uniform float OffsetMapping_Scale : register(c24),\n"
2569 "#endif\n"
2570 "uniform half SpecularPower : register(c36),\n"
2571 "#ifdef HLSL\n"
2572 "out float4 gl_FragData0 : COLOR0,\n"
2573 "out float4 gl_FragData1 : COLOR1\n"
2574 "#else\n"
2575 "out float4 gl_FragColor : COLOR\n"
2576 "#endif\n"
2577 ")\n"
2578 "{\n"
2579 "       float2 TexCoord = TexCoordBoth.xy;\n"
2580 "#ifdef USEOFFSETMAPPING\n"
2581 "       // apply offsetmapping\n"
2582 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2583 "#define TexCoord TexCoordOffset\n"
2584 "#endif\n"
2585 "\n"
2586 "#ifdef USEALPHAKILL\n"
2587 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2588 "               discard;\n"
2589 "#endif\n"
2590 "\n"
2591 "#ifdef USEVERTEXTEXTUREBLEND\n"
2592 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2593 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2594 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2595 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2596 "#endif\n"
2597 "\n"
2598 "#ifdef USEVERTEXTEXTUREBLEND\n"
2599 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2600 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2601 "#else\n"
2602 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2603 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2604 "#endif\n"
2605 "\n"
2606 "#ifdef HLSL\n"
2607 "       gl_FragData0 = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR.xyz) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2608 "       float Depth = VectorR.w / 256.0;\n"
2609 "       float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2610 "//     float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2611 "       depthcolor.yz -= floor(depthcolor.yz);\n"
2612 "       gl_FragData1 = depthcolor;\n"
2613 "#else\n"
2614 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2615 "#endif\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 : register(c8),\n"
2629 "uniform float4x4 ModelViewMatrix : register(c12),\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 "#ifdef HLSL\n"
2643 "float2 Pixel : VPOS,\n"
2644 "#else\n"
2645 "float2 Pixel : WPOS,\n"
2646 "#endif\n"
2647 "float4 ModelViewPosition : TEXCOORD0,\n"
2648 "uniform float4x4 ViewToLight : register(c44),\n"
2649 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2650 "uniform float3 LightPosition : register(c23),\n"
2651 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2652 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2653 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2654 "#ifdef USESPECULAR\n"
2655 "uniform half3 DeferredColor_Specular : register(c11),\n"
2656 "uniform half SpecularPower : register(c36),\n"
2657 "#endif\n"
2658 "uniform sampler Texture_Attenuation : register(s9),\n"
2659 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2660 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2661 "\n"
2662 "#ifdef USECUBEFILTER\n"
2663 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2664 "#endif\n"
2665 "\n"
2666 "#ifdef USESHADOWMAP2D\n"
2667 "# ifdef USESHADOWSAMPLER\n"
2668 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2669 "# else\n"
2670 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2671 "# endif\n"
2672 "#endif\n"
2673 "\n"
2674 "#ifdef USESHADOWMAPVSDCT\n"
2675 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2676 "#endif\n"
2677 "\n"
2678 "#if defined(USESHADOWMAP2D)\n"
2679 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2680 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2681 "#endif\n"
2682 "\n"
2683 "out float4 gl_FragData0 : COLOR0,\n"
2684 "out float4 gl_FragData1 : COLOR1\n"
2685 ")\n"
2686 "{\n"
2687 "       // calculate viewspace pixel position\n"
2688 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2689 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2690 "       float3 position;\n"
2691 "#ifdef HLSL\n"
2692 "       position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2693 "#else\n"
2694 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2695 "#endif\n"
2696 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2697 "       // decode viewspace pixel normal\n"
2698 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2699 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2700 "       // surfacenormal = pixel normal in viewspace\n"
2701 "       // LightVector = pixel to light in viewspace\n"
2702 "       // CubeVector = position in lightspace\n"
2703 "       // eyevector = pixel to view in viewspace\n"
2704 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2705 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2706 "#ifdef USEDIFFUSE\n"
2707 "       // calculate diffuse shading\n"
2708 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2709 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2710 "#endif\n"
2711 "#ifdef USESPECULAR\n"
2712 "       // calculate directional shading\n"
2713 "       float3 eyevector = position * -1.0;\n"
2714 "#  ifdef USEEXACTSPECULARMATH\n"
2715 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2716 "#  else\n"
2717 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2718 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2719 "#  endif\n"
2720 "#endif\n"
2721 "\n"
2722 "#if defined(USESHADOWMAP2D)\n"
2723 "       fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2724 "#ifdef USESHADOWMAPVSDCT\n"
2725 ", Texture_CubeProjection\n"
2726 "#endif\n"
2727 "       ));\n"
2728 "#endif\n"
2729 "\n"
2730 "#ifdef USEDIFFUSE\n"
2731 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2732 "#else\n"
2733 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2734 "#endif\n"
2735 "#ifdef USESPECULAR\n"
2736 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2737 "#else\n"
2738 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2739 "#endif\n"
2740 "\n"
2741 "# ifdef USECUBEFILTER\n"
2742 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2743 "       gl_FragData0.rgb *= cubecolor;\n"
2744 "       gl_FragData1.rgb *= cubecolor;\n"
2745 "# endif\n"
2746 "}\n"
2747 "#endif // FRAGMENT_SHADER\n"
2748 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2749 "\n"
2750 "\n"
2751 "\n"
2752 "\n"
2753 "#ifdef VERTEX_SHADER\n"
2754 "void main\n"
2755 "(\n"
2756 "float4 gl_Vertex : POSITION,\n"
2757 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2758 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2759 "float4 gl_Color : COLOR0,\n"
2760 "#endif\n"
2761 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2762 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2763 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2764 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2765 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2766 "\n"
2767 "uniform float3 EyePosition : register(c24),\n"
2768 "uniform float4x4 TexMatrix : register(c0),\n"
2769 "#ifdef USEVERTEXTEXTUREBLEND\n"
2770 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2771 "#endif\n"
2772 "#ifdef MODE_LIGHTSOURCE\n"
2773 "uniform float4x4 ModelToLight : register(c20),\n"
2774 "#endif\n"
2775 "#ifdef MODE_LIGHTSOURCE\n"
2776 "uniform float3 LightPosition : register(c27),\n"
2777 "#endif\n"
2778 "#ifdef MODE_LIGHTDIRECTION\n"
2779 "uniform float3 LightDir : register(c26),\n"
2780 "#endif\n"
2781 "uniform float4 FogPlane : register(c25),\n"
2782 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2783 "uniform float3 LightPosition : register(c27),\n"
2784 "#endif\n"
2785 "#ifdef USESHADOWMAPORTHO\n"
2786 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2787 "#endif\n"
2788 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2789 "out float4 gl_FrontColor : COLOR,\n"
2790 "#endif\n"
2791 "out float4 TexCoordBoth : TEXCOORD0,\n"
2792 "#ifdef USELIGHTMAP\n"
2793 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2794 "#endif\n"
2795 "#ifdef USEEYEVECTOR\n"
2796 "out float3 EyeVector : TEXCOORD2,\n"
2797 "#endif\n"
2798 "#ifdef USEREFLECTION\n"
2799 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2800 "#endif\n"
2801 "#ifdef USEFOG\n"
2802 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2803 "#endif\n"
2804 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2805 "out float3 LightVector : TEXCOORD1,\n"
2806 "#endif\n"
2807 "#ifdef MODE_LIGHTSOURCE\n"
2808 "out float3 CubeVector : TEXCOORD3,\n"
2809 "#endif\n"
2810 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2811 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2812 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2813 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2814 "#endif\n"
2815 "#ifdef USESHADOWMAPORTHO\n"
2816 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2817 "#endif\n"
2818 "out float4 gl_Position : POSITION\n"
2819 ")\n"
2820 "{\n"
2821 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2822 "#ifdef HLSL\n"
2823 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2824 "#else\n"
2825 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2826 "#endif\n"
2827 "#endif\n"
2828 "       // copy the surface texcoord\n"
2829 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2830 "#ifdef USEVERTEXTEXTUREBLEND\n"
2831 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2832 "#endif\n"
2833 "#ifdef USELIGHTMAP\n"
2834 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2835 "#endif\n"
2836 "\n"
2837 "#ifdef MODE_LIGHTSOURCE\n"
2838 "       // transform vertex position into light attenuation/cubemap space\n"
2839 "       // (-1 to +1 across the light box)\n"
2840 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2841 "\n"
2842 "# ifdef USEDIFFUSE\n"
2843 "       // transform unnormalized light direction into tangent space\n"
2844 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2845 "       //  normalize it per pixel)\n"
2846 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2847 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2848 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2849 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2850 "# endif\n"
2851 "#endif\n"
2852 "\n"
2853 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2854 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2855 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2856 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2857 "#endif\n"
2858 "\n"
2859 "       // transform unnormalized eye direction into tangent space\n"
2860 "#ifdef USEEYEVECTOR\n"
2861 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2862 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2863 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2864 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2865 "#endif\n"
2866 "\n"
2867 "#ifdef USEFOG\n"
2868 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2869 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2870 "#endif\n"
2871 "\n"
2872 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2873 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2874 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2875 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2876 "#endif\n"
2877 "\n"
2878 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2879 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2880 "\n"
2881 "#ifdef USESHADOWMAPORTHO\n"
2882 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2883 "#endif\n"
2884 "\n"
2885 "#ifdef USEREFLECTION\n"
2886 "       ModelViewProjectionPosition = gl_Position;\n"
2887 "#endif\n"
2888 "}\n"
2889 "#endif // VERTEX_SHADER\n"
2890 "\n"
2891 "\n"
2892 "\n"
2893 "\n"
2894 "#ifdef FRAGMENT_SHADER\n"
2895 "void main\n"
2896 "(\n"
2897 "#ifdef USEDEFERREDLIGHTMAP\n"
2898 "#ifdef HLSL\n"
2899 "float2 Pixel : VPOS,\n"
2900 "#else\n"
2901 "float2 Pixel : WPOS,\n"
2902 "#endif\n"
2903 "#endif\n"
2904 "float4 gl_FrontColor : COLOR,\n"
2905 "float4 TexCoordBoth : TEXCOORD0,\n"
2906 "#ifdef USELIGHTMAP\n"
2907 "float2 TexCoordLightmap : TEXCOORD1,\n"
2908 "#endif\n"
2909 "#ifdef USEEYEVECTOR\n"
2910 "float3 EyeVector : TEXCOORD2,\n"
2911 "#endif\n"
2912 "#ifdef USEREFLECTION\n"
2913 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2914 "#endif\n"
2915 "#ifdef USEFOG\n"
2916 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2917 "#endif\n"
2918 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2919 "float3 LightVector : TEXCOORD1,\n"
2920 "#endif\n"
2921 "#ifdef MODE_LIGHTSOURCE\n"
2922 "float3 CubeVector : TEXCOORD3,\n"
2923 "#endif\n"
2924 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2925 "float4 ModelViewPosition : TEXCOORD0,\n"
2926 "#endif\n"
2927 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2928 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2929 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2930 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2931 "#endif\n"
2932 "#ifdef USESHADOWMAPORTHO\n"
2933 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2934 "#endif\n"
2935 "\n"
2936 "uniform sampler Texture_Normal : register(s0),\n"
2937 "uniform sampler Texture_Color : register(s1),\n"
2938 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2939 "uniform sampler Texture_Gloss : register(s2),\n"
2940 "#endif\n"
2941 "#ifdef USEGLOW\n"
2942 "uniform sampler Texture_Glow : register(s3),\n"
2943 "#endif\n"
2944 "#ifdef USEVERTEXTEXTUREBLEND\n"
2945 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2946 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2947 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2948 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2949 "#endif\n"
2950 "#ifdef USEGLOW\n"
2951 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2952 "#endif\n"
2953 "#endif\n"
2954 "#ifdef USECOLORMAPPING\n"
2955 "uniform sampler Texture_Pants : register(s4),\n"
2956 "uniform sampler Texture_Shirt : register(s7),\n"
2957 "#endif\n"
2958 "#ifdef USEFOG\n"
2959 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2960 "uniform sampler Texture_FogMask : register(s8),\n"
2961 "#endif\n"
2962 "#ifdef USELIGHTMAP\n"
2963 "uniform sampler Texture_Lightmap : register(s9),\n"
2964 "#endif\n"
2965 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2966 "uniform sampler Texture_Deluxemap : register(s10),\n"
2967 "#endif\n"
2968 "#ifdef USEREFLECTION\n"
2969 "uniform sampler Texture_Reflection : register(s7),\n"
2970 "#endif\n"
2971 "\n"
2972 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2973 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2974 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2975 "#endif\n"
2976 "#ifdef USEDEFERREDLIGHTMAP\n"
2977 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2978 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2979 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2980 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2981 "#endif\n"
2982 "\n"
2983 "#ifdef USECOLORMAPPING\n"
2984 "uniform half3 Color_Pants : register(c7),\n"
2985 "uniform half3 Color_Shirt : register(c8),\n"
2986 "#endif\n"
2987 "#ifdef USEFOG\n"
2988 "uniform float3 FogColor : register(c16),\n"
2989 "uniform float FogRangeRecip : register(c20),\n"
2990 "uniform float FogPlaneViewDist : register(c19),\n"
2991 "uniform float FogHeightFade : register(c17),\n"
2992 "#endif\n"
2993 "\n"
2994 "#ifdef USEOFFSETMAPPING\n"
2995 "uniform float OffsetMapping_Scale : register(c24),\n"
2996 "#endif\n"
2997 "\n"
2998 "#ifdef USEDEFERREDLIGHTMAP\n"
2999 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3000 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3001 "uniform half3 DeferredMod_Specular : register(c13),\n"
3002 "#endif\n"
3003 "uniform half3 Color_Ambient : register(c3),\n"
3004 "uniform half3 Color_Diffuse : register(c4),\n"
3005 "uniform half3 Color_Specular : register(c5),\n"
3006 "uniform half SpecularPower : register(c36),\n"
3007 "#ifdef USEGLOW\n"
3008 "uniform half3 Color_Glow : register(c6),\n"
3009 "#endif\n"
3010 "uniform half Alpha : register(c0),\n"
3011 "#ifdef USEREFLECTION\n"
3012 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3013 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3014 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3015 "uniform half4 ReflectColor : register(c26),\n"
3016 "#endif\n"
3017 "#ifdef USEREFLECTCUBE\n"
3018 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3019 "uniform sampler Texture_ReflectMask : register(s5),\n"
3020 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3021 "#endif\n"
3022 "#ifdef MODE_LIGHTDIRECTION\n"
3023 "uniform half3 LightColor : register(c21),\n"
3024 "#endif\n"
3025 "#ifdef MODE_LIGHTSOURCE\n"
3026 "uniform half3 LightColor : register(c21),\n"
3027 "#endif\n"
3028 "\n"
3029 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3030 "uniform sampler Texture_Attenuation : register(s9),\n"
3031 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3032 "#endif\n"
3033 "\n"
3034 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3035 "\n"
3036 "#ifdef USESHADOWMAP2D\n"
3037 "# ifdef USESHADOWSAMPLER\n"
3038 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3039 "# else\n"
3040 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3041 "# endif\n"
3042 "#endif\n"
3043 "\n"
3044 "#ifdef USESHADOWMAPVSDCT\n"
3045 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3046 "#endif\n"
3047 "\n"
3048 "#if defined(USESHADOWMAP2D)\n"
3049 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3050 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3051 "#endif\n"
3052 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3053 "\n"
3054 "out float4 gl_FragColor : COLOR\n"
3055 ")\n"
3056 "{\n"
3057 "       float2 TexCoord = TexCoordBoth.xy;\n"
3058 "#ifdef USEVERTEXTEXTUREBLEND\n"
3059 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3060 "#endif\n"
3061 "#ifdef USEOFFSETMAPPING\n"
3062 "       // apply offsetmapping\n"
3063 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3064 "#define TexCoord TexCoordOffset\n"
3065 "#endif\n"
3066 "\n"
3067 "       // combine the diffuse textures (base, pants, shirt)\n"
3068 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3069 "#ifdef USEALPHAKILL\n"
3070 "       if (color.a < 0.5)\n"
3071 "               discard;\n"
3072 "#endif\n"
3073 "       color.a *= Alpha;\n"
3074 "#ifdef USECOLORMAPPING\n"
3075 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3076 "#endif\n"
3077 "#ifdef USEVERTEXTEXTUREBLEND\n"
3078 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3079 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3080 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3081 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3082 "       color.a = 1.0;\n"
3083 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3084 "#endif\n"
3085 "\n"
3086 "       // get the surface normal\n"
3087 "#ifdef USEVERTEXTEXTUREBLEND\n"
3088 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3089 "#else\n"
3090 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3091 "#endif\n"
3092 "\n"
3093 "       // get the material colors\n"
3094 "       half3 diffusetex = color.rgb;\n"
3095 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3096 "# ifdef USEVERTEXTEXTUREBLEND\n"
3097 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3098 "# else\n"
3099 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3100 "# endif\n"
3101 "#endif\n"
3102 "\n"
3103 "#ifdef USEREFLECTCUBE\n"
3104 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3105 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3106 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3107 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3108 "#endif\n"
3109 "\n"
3110 "\n"
3111 "\n"
3112 "\n"
3113 "#ifdef MODE_LIGHTSOURCE\n"
3114 "       // light source\n"
3115 "#ifdef USEDIFFUSE\n"
3116 "       half3 lightnormal = half3(normalize(LightVector));\n"
3117 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3118 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3119 "#ifdef USESPECULAR\n"
3120 "#ifdef USEEXACTSPECULARMATH\n"
3121 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3122 "#else\n"
3123 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3124 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3125 "#endif\n"
3126 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3127 "#endif\n"
3128 "#else\n"
3129 "       color.rgb = diffusetex * Color_Ambient;\n"
3130 "#endif\n"
3131 "       color.rgb *= LightColor;\n"
3132 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3133 "#if defined(USESHADOWMAP2D)\n"
3134 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3135 "#ifdef USESHADOWMAPVSDCT\n"
3136 ", Texture_CubeProjection\n"
3137 "#endif\n"
3138 "       ));\n"
3139 "\n"
3140 "#endif\n"
3141 "# ifdef USECUBEFILTER\n"
3142 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3143 "# endif\n"
3144 "\n"
3145 "#ifdef USESHADOWMAP2D\n"
3146 "#ifdef USESHADOWMAPVSDCT\n"
3147 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3148 "#else\n"
3149 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3150 "#endif\n"
3151 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3152 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3153 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3154 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3155 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3156 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3157 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3158 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3159 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3160 "//     color.r = half(shadowmaptc.z);\n"
3161 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3162 "//     color.r = half(shadowmaptc.z);\n"
3163 "//     color.r = 1;\n"
3164 "//     color.rgb = abs(CubeVector);\n"
3165 "#endif\n"
3166 "//     color.rgb = half3(1,1,1);\n"
3167 "#endif // MODE_LIGHTSOURCE\n"
3168 "\n"
3169 "\n"
3170 "\n"
3171 "\n"
3172 "#ifdef MODE_LIGHTDIRECTION\n"
3173 "#define SHADING\n"
3174 "#ifdef USEDIFFUSE\n"
3175 "       half3 lightnormal = half3(normalize(LightVector));\n"
3176 "#endif\n"
3177 "#define lightcolor LightColor\n"
3178 "#endif // MODE_LIGHTDIRECTION\n"
3179 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3180 "#define SHADING\n"
3181 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3182 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3183 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3184 "       // convert modelspace light vector to tangentspace\n"
3185 "       half3 lightnormal;\n"
3186 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3187 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3188 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3189 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3190 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3191 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3192 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3193 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3194 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3195 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3196 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3197 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3198 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3199 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3200 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3201 "#define SHADING\n"
3202 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3203 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3204 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3205 "#endif\n"
3206 "\n"
3207 "\n"
3208 "\n"
3209 "\n"
3210 "#ifdef MODE_FAKELIGHT\n"
3211 "#define SHADING\n"
3212 "half3 lightnormal = half3(normalize(EyeVector));\n"
3213 "half3 lightcolor = half3(1.0);\n"
3214 "#endif // MODE_FAKELIGHT\n"
3215 "\n"
3216 "\n"
3217 "\n"
3218 "\n"
3219 "#ifdef MODE_LIGHTMAP\n"
3220 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3221 "#endif // MODE_LIGHTMAP\n"
3222 "#ifdef MODE_VERTEXCOLOR\n"
3223 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3224 "#endif // MODE_VERTEXCOLOR\n"
3225 "#ifdef MODE_FLATCOLOR\n"
3226 "       color.rgb = diffusetex * Color_Ambient;\n"
3227 "#endif // MODE_FLATCOLOR\n"
3228 "\n"
3229 "\n"
3230 "\n"
3231 "\n"
3232 "#ifdef SHADING\n"
3233 "# ifdef USEDIFFUSE\n"
3234 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3235 "#  ifdef USESPECULAR\n"
3236 "#   ifdef USEEXACTSPECULARMATH\n"
3237 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3238 "#   else\n"
3239 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3240 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3241 "#   endif\n"
3242 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3243 "#  else\n"
3244 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3245 "#  endif\n"
3246 "# else\n"
3247 "       color.rgb = diffusetex * Color_Ambient;\n"
3248 "# endif\n"
3249 "#endif\n"
3250 "\n"
3251 "#ifdef USESHADOWMAPORTHO\n"
3252 "       color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3253 "#endif\n"
3254 "\n"
3255 "#ifdef USEDEFERREDLIGHTMAP\n"
3256 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3257 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3258 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3259 "//     color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3260 "//     color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3261 "#endif\n"
3262 "\n"
3263 "#ifdef USEGLOW\n"
3264 "#ifdef USEVERTEXTEXTUREBLEND\n"
3265 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3266 "#else\n"
3267 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3268 "#endif\n"
3269 "#endif\n"
3270 "\n"
3271 "#ifdef USEFOG\n"
3272 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3273 "#endif\n"
3274 "\n"
3275 "       // 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"
3276 "#ifdef USEREFLECTION\n"
3277 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3278 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3279 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3280 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3281 "       // FIXME temporary hack to detect the case that the reflection\n"
3282 "       // gets blackened at edges due to leaving the area that contains actual\n"
3283 "       // content.\n"
3284 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3285 "       // 'appening.\n"
3286 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3287 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3288 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3289 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3290 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3291 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3292 "#endif\n"
3293 "\n"
3294 "       gl_FragColor = float4(color);\n"
3295 "}\n"
3296 "#endif // FRAGMENT_SHADER\n"
3297 "\n"
3298 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3299 "#endif // !MODE_DEFERREDGEOMETRY\n"
3300 "#endif // !MODE_WATER\n"
3301 "#endif // !MODE_REFRACTION\n"
3302 "#endif // !MODE_BLOOMBLUR\n"
3303 "#endif // !MODE_GENERIC\n"
3304 "#endif // !MODE_POSTPROCESS\n"
3305 "#endif // !MODE_SHOWDEPTH\n"
3306 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3307 ;
3308
3309 char *glslshaderstring = NULL;
3310 char *cgshaderstring = NULL;
3311 char *hlslshaderstring = NULL;
3312
3313 //=======================================================================================================================================================
3314
3315 typedef struct shaderpermutationinfo_s
3316 {
3317         const char *pretext;
3318         const char *name;
3319 }
3320 shaderpermutationinfo_t;
3321
3322 typedef struct shadermodeinfo_s
3323 {
3324         const char *vertexfilename;
3325         const char *geometryfilename;
3326         const char *fragmentfilename;
3327         const char *pretext;
3328         const char *name;
3329 }
3330 shadermodeinfo_t;
3331
3332 typedef enum shaderpermutation_e
3333 {
3334         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3335         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3336         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3337         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3338         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3339         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3340         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3341         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3342         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3343         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3344         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3345         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3346         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3347         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3348         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3349         SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3350         SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3351         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3352         SHADERPERMUTATION_SHADOWMAP2D = 1<<18, ///< (lightsource) use shadowmap texture as light filter
3353         SHADERPERMUTATION_SHADOWMAPPCF = 1<<19, ///< (lightsource) use percentage closer filtering on shadowmap test results
3354         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<20, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3355         SHADERPERMUTATION_SHADOWSAMPLER = 1<<21, ///< (lightsource) use hardware shadowmap test
3356         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<22, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3357         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<23, //< (lightsource) use orthographic shadowmap projection
3358         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3359         SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3360         SHADERPERMUTATION_REFLECTCUBE = 1<<26, ///< fake reflections using global cubemap (not HDRI light probe)
3361         SHADERPERMUTATION_NORMALMAPSCROLLBLEND = 1<<27, // (water) counter-direction normalmaps scrolling
3362         SHADERPERMUTATION_LIMIT = 1<<28, ///< size of permutations array
3363         SHADERPERMUTATION_COUNT = 28 ///< size of shaderpermutationinfo array
3364 }
3365 shaderpermutation_t;
3366
3367 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3368 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3369 {
3370         {"#define USEDIFFUSE\n", " diffuse"},
3371         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3372         {"#define USEVIEWTINT\n", " viewtint"},
3373         {"#define USECOLORMAPPING\n", " colormapping"},
3374         {"#define USESATURATION\n", " saturation"},
3375         {"#define USEFOGINSIDE\n", " foginside"},
3376         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3377         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3378         {"#define USEGAMMARAMPS\n", " gammaramps"},
3379         {"#define USECUBEFILTER\n", " cubefilter"},
3380         {"#define USEGLOW\n", " glow"},
3381         {"#define USEBLOOM\n", " bloom"},
3382         {"#define USESPECULAR\n", " specular"},
3383         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3384         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3385         {"#define USEREFLECTION\n", " reflection"},
3386         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3387         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3388         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3389         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3390         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3391         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3392         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3393         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3394         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3395         {"#define USEALPHAKILL\n", " alphakill"},
3396         {"#define USEREFLECTCUBE\n", " reflectcube"},
3397         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3398 };
3399
3400 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3401 typedef enum shadermode_e
3402 {
3403         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3404         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3405         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3406         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3407         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3408         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3409         SHADERMODE_FAKELIGHT, ///< (fakelight) modulate texture by "fake" lighting (no lightmaps, no nothing)
3410         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3411         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3412         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3413         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3414         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3415         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3416         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3417         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3418         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3419         SHADERMODE_COUNT
3420 }
3421 shadermode_t;
3422
3423 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3424 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3425 {
3426         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3427         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3428         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3429         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3430         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3431         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3432         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3433         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3434         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3435         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3436         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3437         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3438         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3439         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3440         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3441         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3442 };
3443
3444 #ifdef SUPPORTCG
3445 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3446 {
3447         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3448         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3449         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3450         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3451         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3452         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3453         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
3454         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3455         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3456         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3457         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3458         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3459         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3460         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3461         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3462         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3463 };
3464 #endif
3465
3466 #ifdef SUPPORTD3D
3467 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3468 {
3469         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3470         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3471         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3472         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3473         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3474         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3475         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3476         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3477         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3478         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3479         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3480         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3481         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3482         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3483         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3484 };
3485 #endif
3486
3487 struct r_glsl_permutation_s;
3488 typedef struct r_glsl_permutation_s
3489 {
3490         /// hash lookup data
3491         struct r_glsl_permutation_s *hashnext;
3492         unsigned int mode;
3493         unsigned int permutation;
3494
3495         /// indicates if we have tried compiling this permutation already
3496         qboolean compiled;
3497         /// 0 if compilation failed
3498         int program;
3499         /// locations of detected uniforms in program object, or -1 if not found
3500         int loc_Texture_First;
3501         int loc_Texture_Second;
3502         int loc_Texture_GammaRamps;
3503         int loc_Texture_Normal;
3504         int loc_Texture_Color;
3505         int loc_Texture_Gloss;
3506         int loc_Texture_Glow;
3507         int loc_Texture_SecondaryNormal;
3508         int loc_Texture_SecondaryColor;
3509         int loc_Texture_SecondaryGloss;
3510         int loc_Texture_SecondaryGlow;
3511         int loc_Texture_Pants;
3512         int loc_Texture_Shirt;
3513         int loc_Texture_FogHeightTexture;
3514         int loc_Texture_FogMask;
3515         int loc_Texture_Lightmap;
3516         int loc_Texture_Deluxemap;
3517         int loc_Texture_Attenuation;
3518         int loc_Texture_Cube;
3519         int loc_Texture_Refraction;
3520         int loc_Texture_Reflection;
3521         int loc_Texture_ShadowMap2D;
3522         int loc_Texture_CubeProjection;
3523         int loc_Texture_ScreenDepth;
3524         int loc_Texture_ScreenNormalMap;
3525         int loc_Texture_ScreenDiffuse;
3526         int loc_Texture_ScreenSpecular;
3527         int loc_Texture_ReflectMask;
3528         int loc_Texture_ReflectCube;
3529         int loc_Alpha;
3530         int loc_BloomBlur_Parameters;
3531         int loc_ClientTime;
3532         int loc_Color_Ambient;
3533         int loc_Color_Diffuse;
3534         int loc_Color_Specular;
3535         int loc_Color_Glow;
3536         int loc_Color_Pants;
3537         int loc_Color_Shirt;
3538         int loc_DeferredColor_Ambient;
3539         int loc_DeferredColor_Diffuse;
3540         int loc_DeferredColor_Specular;
3541         int loc_DeferredMod_Diffuse;
3542         int loc_DeferredMod_Specular;
3543         int loc_DistortScaleRefractReflect;
3544         int loc_EyePosition;
3545         int loc_FogColor;
3546         int loc_FogHeightFade;
3547         int loc_FogPlane;
3548         int loc_FogPlaneViewDist;
3549         int loc_FogRangeRecip;
3550         int loc_LightColor;
3551         int loc_LightDir;
3552         int loc_LightPosition;
3553         int loc_OffsetMapping_Scale;
3554         int loc_PixelSize;
3555         int loc_ReflectColor;
3556         int loc_ReflectFactor;
3557         int loc_ReflectOffset;
3558         int loc_RefractColor;
3559         int loc_Saturation;
3560         int loc_ScreenCenterRefractReflect;
3561         int loc_ScreenScaleRefractReflect;
3562         int loc_ScreenToDepth;
3563         int loc_ShadowMap_Parameters;
3564         int loc_ShadowMap_TextureScale;
3565         int loc_SpecularPower;
3566         int loc_UserVec1;
3567         int loc_UserVec2;
3568         int loc_UserVec3;
3569         int loc_UserVec4;
3570         int loc_ViewTintColor;
3571         int loc_ViewToLight;
3572         int loc_ModelToLight;
3573         int loc_TexMatrix;
3574         int loc_BackgroundTexMatrix;
3575         int loc_ModelViewProjectionMatrix;
3576         int loc_ModelViewMatrix;
3577         int loc_PixelToScreenTexCoord;
3578         int loc_ModelToReflectCube;
3579         int loc_ShadowMapMatrix;
3580         int loc_BloomColorSubtract;
3581         int loc_NormalmapScrollBlend;
3582 }
3583 r_glsl_permutation_t;
3584
3585 #define SHADERPERMUTATION_HASHSIZE 256
3586
3587
3588 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3589 // these can NOT degrade! only use for simple stuff
3590 enum
3591 {
3592         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0
3593 };
3594 #define SHADERSTATICPARMS_COUNT 1
3595
3596 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3597 static int shaderstaticparms_count = 0;
3598
3599 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3600 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3601 qboolean R_CompileShader_CheckStaticParms(void)
3602 {
3603         static int r_compileshader_staticparms_save[1];
3604         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3605         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3606
3607         // detect all
3608         if (r_glsl_saturation_redcompensate.integer)
3609                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3610
3611         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms));
3612 }
3613
3614 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3615         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3616                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3617         else \
3618                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3619 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3620 {
3621         shaderstaticparms_count = 0;
3622
3623         // emit all
3624         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3625 }
3626
3627
3628 /// information about each possible shader permutation
3629 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3630 /// currently selected permutation
3631 r_glsl_permutation_t *r_glsl_permutation;
3632 /// storage for permutations linked in the hash table
3633 memexpandablearray_t r_glsl_permutationarray;
3634
3635 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3636 {
3637         //unsigned int hashdepth = 0;
3638         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3639         r_glsl_permutation_t *p;
3640         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3641         {
3642                 if (p->mode == mode && p->permutation == permutation)
3643                 {
3644                         //if (hashdepth > 10)
3645                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3646                         return p;
3647                 }
3648                 //hashdepth++;
3649         }
3650         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3651         p->mode = mode;
3652         p->permutation = permutation;
3653         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3654         r_glsl_permutationhash[mode][hashindex] = p;
3655         //if (hashdepth > 10)
3656         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3657         return p;
3658 }
3659
3660 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3661 {
3662         char *shaderstring;
3663         if (!filename || !filename[0])
3664                 return NULL;
3665         if (!strcmp(filename, "glsl/default.glsl"))
3666         {
3667                 if (!glslshaderstring)
3668                 {
3669                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3670                         if (glslshaderstring)
3671                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3672                         else
3673                                 glslshaderstring = (char *)builtinshaderstring;
3674                 }
3675                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3676                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3677                 return shaderstring;
3678         }
3679         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3680         if (shaderstring)
3681         {
3682                 if (printfromdisknotice)
3683                         Con_DPrintf("from disk %s... ", filename);
3684                 return shaderstring;
3685         }
3686         return shaderstring;
3687 }
3688
3689 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3690 {
3691         int i;
3692         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3693         char *vertexstring, *geometrystring, *fragmentstring;
3694         char permutationname[256];
3695         int vertstrings_count = 0;
3696         int geomstrings_count = 0;
3697         int fragstrings_count = 0;
3698         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3699         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3700         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3701
3702         if (p->compiled)
3703                 return;
3704         p->compiled = true;
3705         p->program = 0;
3706
3707         permutationname[0] = 0;
3708         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3709         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3710         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3711
3712         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3713
3714         // the first pretext is which type of shader to compile as
3715         // (later these will all be bound together as a program object)
3716         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3717         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3718         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3719
3720         // the second pretext is the mode (for example a light source)
3721         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3722         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3723         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3724         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3725
3726         // now add all the permutation pretexts
3727         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3728         {
3729                 if (permutation & (1<<i))
3730                 {
3731                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3732                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3733                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3734                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3735                 }
3736                 else
3737                 {
3738                         // keep line numbers correct
3739                         vertstrings_list[vertstrings_count++] = "\n";
3740                         geomstrings_list[geomstrings_count++] = "\n";
3741                         fragstrings_list[fragstrings_count++] = "\n";
3742                 }
3743         }
3744
3745         // add static parms
3746         R_CompileShader_AddStaticParms(mode, permutation);
3747         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3748         vertstrings_count += shaderstaticparms_count;
3749         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3750         geomstrings_count += shaderstaticparms_count;
3751         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3752         fragstrings_count += shaderstaticparms_count;
3753
3754         // now append the shader text itself
3755         vertstrings_list[vertstrings_count++] = vertexstring;
3756         geomstrings_list[geomstrings_count++] = geometrystring;
3757         fragstrings_list[fragstrings_count++] = fragmentstring;
3758
3759         // if any sources were NULL, clear the respective list
3760         if (!vertexstring)
3761                 vertstrings_count = 0;
3762         if (!geometrystring)
3763                 geomstrings_count = 0;
3764         if (!fragmentstring)
3765                 fragstrings_count = 0;
3766
3767         // compile the shader program
3768         if (vertstrings_count + geomstrings_count + fragstrings_count)
3769                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3770         if (p->program)
3771         {
3772                 CHECKGLERROR
3773                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3774                 // look up all the uniform variable names we care about, so we don't
3775                 // have to look them up every time we set them
3776
3777                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3778                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3779                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3780                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3781                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3782                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3783                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3784                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3785                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3786                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3787                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3788                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3789                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3790                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3791                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3792                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3793                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3794                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3795                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3796                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3797                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3798                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3799                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3800                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3801                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3802                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3803                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3804                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3805                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3806                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3807                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3808                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3809                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3810                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3811                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3812                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3813                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3814                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3815                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3816                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3817                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3818                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3819                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3820                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3821                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3822                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3823                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3824                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3825                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3826                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3827                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3828                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3829                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3830                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3831                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3832                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3833                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3834                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3835                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3836                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3837                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3838                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3839                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3840                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3841                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3842                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3843                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3844                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3845                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3846                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3847                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3848                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3849                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3850                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3851                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3852                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3853                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3854                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3855                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3856                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3857                 p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3858                 p->loc_NormalmapScrollBlend       = qglGetUniformLocationARB(p->program, "NormalmapScrollBlend");
3859                 // initialize the samplers to refer to the texture units we use
3860                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3861                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3862                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3863                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3864                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3865                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3866                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3867                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3868                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3869                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3870                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3871                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3872                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3873                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3874                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3875                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3876                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3877                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3878                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3879                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3880                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3881                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3882                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3883                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3884                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3885                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3886                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3887                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3888                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3889                 CHECKGLERROR
3890                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3891         }
3892         else
3893                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3894
3895         // free the strings
3896         if (vertexstring)
3897                 Mem_Free(vertexstring);
3898         if (geometrystring)
3899                 Mem_Free(geometrystring);
3900         if (fragmentstring)
3901                 Mem_Free(fragmentstring);
3902 }
3903
3904 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3905 {
3906         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3907         if (r_glsl_permutation != perm)
3908         {
3909                 r_glsl_permutation = perm;
3910                 if (!r_glsl_permutation->program)
3911                 {
3912                         if (!r_glsl_permutation->compiled)
3913                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3914                         if (!r_glsl_permutation->program)
3915                         {
3916                                 // remove features until we find a valid permutation
3917                                 int i;
3918                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3919                                 {
3920                                         // reduce i more quickly whenever it would not remove any bits
3921                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3922                                         if (!(permutation & j))
3923                                                 continue;
3924                                         permutation -= j;
3925                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3926                                         if (!r_glsl_permutation->compiled)
3927                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3928                                         if (r_glsl_permutation->program)
3929                                                 break;
3930                                 }
3931                                 if (i >= SHADERPERMUTATION_COUNT)
3932                                 {
3933                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3934                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3935                                         qglUseProgramObjectARB(0);CHECKGLERROR
3936                                         return; // no bit left to clear, entire mode is broken
3937                                 }
3938                         }
3939                 }
3940                 CHECKGLERROR
3941                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3942         }
3943         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3944         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3945         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3946 }
3947
3948 #ifdef SUPPORTCG
3949 #include <Cg/cgGL.h>
3950 struct r_cg_permutation_s;
3951 typedef struct r_cg_permutation_s
3952 {
3953         /// hash lookup data
3954         struct r_cg_permutation_s *hashnext;
3955         unsigned int mode;
3956         unsigned int permutation;
3957
3958         /// indicates if we have tried compiling this permutation already
3959         qboolean compiled;
3960         /// 0 if compilation failed
3961         CGprogram vprogram;
3962         CGprogram fprogram;
3963         /// locations of detected parameters in programs, or NULL if not found
3964         CGparameter vp_EyePosition;
3965         CGparameter vp_FogPlane;
3966         CGparameter vp_LightDir;
3967         CGparameter vp_LightPosition;
3968         CGparameter vp_ModelToLight;
3969         CGparameter vp_TexMatrix;
3970         CGparameter vp_BackgroundTexMatrix;
3971         CGparameter vp_ModelViewProjectionMatrix;
3972         CGparameter vp_ModelViewMatrix;
3973         CGparameter vp_ShadowMapMatrix;
3974
3975         CGparameter fp_Texture_First;
3976         CGparameter fp_Texture_Second;
3977         CGparameter fp_Texture_GammaRamps;
3978         CGparameter fp_Texture_Normal;
3979         CGparameter fp_Texture_Color;
3980         CGparameter fp_Texture_Gloss;
3981         CGparameter fp_Texture_Glow;
3982         CGparameter fp_Texture_SecondaryNormal;
3983         CGparameter fp_Texture_SecondaryColor;
3984         CGparameter fp_Texture_SecondaryGloss;
3985         CGparameter fp_Texture_SecondaryGlow;
3986         CGparameter fp_Texture_Pants;
3987         CGparameter fp_Texture_Shirt;
3988         CGparameter fp_Texture_FogHeightTexture;
3989         CGparameter fp_Texture_FogMask;
3990         CGparameter fp_Texture_Lightmap;
3991         CGparameter fp_Texture_Deluxemap;
3992         CGparameter fp_Texture_Attenuation;
3993         CGparameter fp_Texture_Cube;
3994         CGparameter fp_Texture_Refraction;
3995         CGparameter fp_Texture_Reflection;
3996         CGparameter fp_Texture_ShadowMap2D;
3997         CGparameter fp_Texture_CubeProjection;
3998         CGparameter fp_Texture_ScreenDepth;
3999         CGparameter fp_Texture_ScreenNormalMap;
4000         CGparameter fp_Texture_ScreenDiffuse;
4001         CGparameter fp_Texture_ScreenSpecular;
4002         CGparameter fp_Texture_ReflectMask;
4003         CGparameter fp_Texture_ReflectCube;
4004         CGparameter fp_Alpha;
4005         CGparameter fp_BloomBlur_Parameters;
4006         CGparameter fp_ClientTime;
4007         CGparameter fp_Color_Ambient;
4008         CGparameter fp_Color_Diffuse;
4009         CGparameter fp_Color_Specular;
4010         CGparameter fp_Color_Glow;
4011         CGparameter fp_Color_Pants;
4012         CGparameter fp_Color_Shirt;
4013         CGparameter fp_DeferredColor_Ambient;
4014         CGparameter fp_DeferredColor_Diffuse;
4015         CGparameter fp_DeferredColor_Specular;
4016         CGparameter fp_DeferredMod_Diffuse;
4017         CGparameter fp_DeferredMod_Specular;
4018         CGparameter fp_DistortScaleRefractReflect;
4019         CGparameter fp_EyePosition;
4020         CGparameter fp_FogColor;
4021         CGparameter fp_FogHeightFade;
4022         CGparameter fp_FogPlane;
4023         CGparameter fp_FogPlaneViewDist;
4024         CGparameter fp_FogRangeRecip;
4025         CGparameter fp_LightColor;
4026         CGparameter fp_LightDir;
4027         CGparameter fp_LightPosition;
4028         CGparameter fp_OffsetMapping_Scale;
4029         CGparameter fp_PixelSize;
4030         CGparameter fp_ReflectColor;
4031         CGparameter fp_ReflectFactor;
4032         CGparameter fp_ReflectOffset;
4033         CGparameter fp_RefractColor;
4034         CGparameter fp_Saturation;
4035         CGparameter fp_ScreenCenterRefractReflect;
4036         CGparameter fp_ScreenScaleRefractReflect;
4037         CGparameter fp_ScreenToDepth;
4038         CGparameter fp_ShadowMap_Parameters;
4039         CGparameter fp_ShadowMap_TextureScale;
4040         CGparameter fp_SpecularPower;
4041         CGparameter fp_UserVec1;
4042         CGparameter fp_UserVec2;
4043         CGparameter fp_UserVec3;
4044         CGparameter fp_UserVec4;
4045         CGparameter fp_ViewTintColor;
4046         CGparameter fp_ViewToLight;
4047         CGparameter fp_PixelToScreenTexCoord;
4048         CGparameter fp_ModelToReflectCube;
4049         CGparameter fp_BloomColorSubtract;
4050         CGparameter fp_NormalmapScrollBlend;
4051 }
4052 r_cg_permutation_t;
4053
4054 /// information about each possible shader permutation
4055 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4056 /// currently selected permutation
4057 r_cg_permutation_t *r_cg_permutation;
4058 /// storage for permutations linked in the hash table
4059 memexpandablearray_t r_cg_permutationarray;
4060
4061 #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));}}
4062
4063 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4064 {
4065         //unsigned int hashdepth = 0;
4066         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4067         r_cg_permutation_t *p;
4068         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4069         {
4070                 if (p->mode == mode && p->permutation == permutation)
4071                 {
4072                         //if (hashdepth > 10)
4073                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4074                         return p;
4075                 }
4076                 //hashdepth++;
4077         }
4078         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4079         p->mode = mode;
4080         p->permutation = permutation;
4081         p->hashnext = r_cg_permutationhash[mode][hashindex];
4082         r_cg_permutationhash[mode][hashindex] = p;
4083         //if (hashdepth > 10)
4084         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4085         return p;
4086 }
4087
4088 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4089 {
4090         char *shaderstring;
4091         if (!filename || !filename[0])
4092                 return NULL;
4093         if (!strcmp(filename, "cg/default.cg"))
4094         {
4095                 if (!cgshaderstring)
4096                 {
4097                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4098                         if (cgshaderstring)
4099                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4100                         else
4101                                 cgshaderstring = (char *)builtincgshaderstring;
4102                 }
4103                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4104                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4105                 return shaderstring;
4106         }
4107         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4108         if (shaderstring)
4109         {
4110                 if (printfromdisknotice)
4111                         Con_DPrintf("from disk %s... ", filename);
4112                 return shaderstring;
4113         }
4114         return shaderstring;
4115 }
4116
4117 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4118 {
4119         // TODO: load or create .fp and .vp shader files
4120 }
4121
4122 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4123 {
4124         int i;
4125         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4126         int vertstring_length = 0;
4127         int geomstring_length = 0;
4128         int fragstring_length = 0;
4129         char *t;
4130         char *vertexstring, *geometrystring, *fragmentstring;
4131         char *vertstring, *geomstring, *fragstring;
4132         char permutationname[256];
4133         char cachename[256];
4134         CGprofile vertexProfile;
4135         CGprofile fragmentProfile;
4136         int vertstrings_count = 0;
4137         int geomstrings_count = 0;
4138         int fragstrings_count = 0;
4139         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4140         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4141         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4142
4143         if (p->compiled)
4144                 return;
4145         p->compiled = true;
4146         p->vprogram = NULL;
4147         p->fprogram = NULL;
4148
4149         permutationname[0] = 0;
4150         cachename[0] = 0;
4151         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4152         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4153         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4154
4155         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4156         strlcat(cachename, "cg/", sizeof(cachename));
4157
4158         // the first pretext is which type of shader to compile as
4159         // (later these will all be bound together as a program object)
4160         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4161         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4162         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4163
4164         // the second pretext is the mode (for example a light source)
4165         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4166         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4167         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4168         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4169         strlcat(cachename, modeinfo->name, sizeof(cachename));
4170
4171         // now add all the permutation pretexts
4172         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4173         {
4174                 if (permutation & (1<<i))
4175                 {
4176                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4177                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4178                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4179                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4180                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4181                 }
4182                 else
4183                 {
4184                         // keep line numbers correct
4185                         vertstrings_list[vertstrings_count++] = "\n";
4186                         geomstrings_list[geomstrings_count++] = "\n";
4187                         fragstrings_list[fragstrings_count++] = "\n";
4188                 }
4189         }
4190
4191         // add static parms
4192         R_CompileShader_AddStaticParms(mode, permutation);
4193         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4194         vertstrings_count += shaderstaticparms_count;
4195         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4196         geomstrings_count += shaderstaticparms_count;
4197         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4198         fragstrings_count += shaderstaticparms_count;
4199
4200         // replace spaces in the cachename with _ characters
4201         for (i = 0;cachename[i];i++)
4202                 if (cachename[i] == ' ')
4203                         cachename[i] = '_';
4204
4205         // now append the shader text itself
4206         vertstrings_list[vertstrings_count++] = vertexstring;
4207         geomstrings_list[geomstrings_count++] = geometrystring;
4208         fragstrings_list[fragstrings_count++] = fragmentstring;
4209
4210         // if any sources were NULL, clear the respective list
4211         if (!vertexstring)
4212                 vertstrings_count = 0;
4213         if (!geometrystring)
4214                 geomstrings_count = 0;
4215         if (!fragmentstring)
4216                 fragstrings_count = 0;
4217
4218         vertstring_length = 0;
4219         for (i = 0;i < vertstrings_count;i++)
4220                 vertstring_length += strlen(vertstrings_list[i]);
4221         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4222         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4223                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4224
4225         geomstring_length = 0;
4226         for (i = 0;i < geomstrings_count;i++)
4227                 geomstring_length += strlen(geomstrings_list[i]);
4228         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4229         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4230                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4231
4232         fragstring_length = 0;
4233         for (i = 0;i < fragstrings_count;i++)
4234                 fragstring_length += strlen(fragstrings_list[i]);
4235         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4236         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4237                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4238
4239         CHECKGLERROR
4240         CHECKCGERROR
4241         //vertexProfile = CG_PROFILE_ARBVP1;
4242         //fragmentProfile = CG_PROFILE_ARBFP1;
4243         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4244         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4245         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4246         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4247         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4248         CHECKGLERROR
4249
4250         // try to load the cached shader, or generate one
4251         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4252
4253         // if caching failed, do a dynamic compile for now
4254         CHECKCGERROR
4255         if (vertstring[0] && !p->vprogram)
4256                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4257         CHECKCGERROR
4258         if (fragstring[0] && !p->fprogram)
4259                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4260         CHECKCGERROR
4261
4262         // look up all the uniform variable names we care about, so we don't
4263         // have to look them up every time we set them
4264         if (p->vprogram)
4265         {
4266                 CHECKCGERROR
4267                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4268                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4269                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4270                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4271                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4272                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4273                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4274                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4275                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4276                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4277                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4278                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4279                 CHECKCGERROR
4280         }
4281         if (p->fprogram)
4282         {
4283                 CHECKCGERROR
4284                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4285                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4286                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4287                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4288                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4289                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4290                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4291                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4292                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4293                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4294                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4295                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4296                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4297                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4298                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4299                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4300                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4301                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4302                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4303                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4304                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4305                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4306                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4307                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4308                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4309                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4310                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4311                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4312                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4313                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4314                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4315                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4316                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4317                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4318                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4319                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4320                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4321                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4322                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4323                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4324                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4325                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4326                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4327                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4328                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4329                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4330                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4331                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4332                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4333                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4334                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4335                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4336                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4337                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4338                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4339                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4340                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4341                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4342                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4343                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4344                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4345                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4346                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4347                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4348                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4349                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4350                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4351                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4352                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4353                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4354                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4355                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4356                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4357                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4358                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4359                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4360                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4361                 p->fp_NormalmapScrollBlend       = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4362                 CHECKCGERROR
4363         }
4364
4365         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4366                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4367         else
4368                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4369
4370         // free the strings
4371         if (vertstring)
4372                 Mem_Free(vertstring);
4373         if (geomstring)
4374                 Mem_Free(geomstring);
4375         if (fragstring)
4376                 Mem_Free(fragstring);
4377         if (vertexstring)
4378                 Mem_Free(vertexstring);
4379         if (geometrystring)
4380                 Mem_Free(geometrystring);
4381         if (fragmentstring)
4382                 Mem_Free(fragmentstring);
4383 }
4384
4385 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4386 {
4387         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4388         CHECKGLERROR
4389         CHECKCGERROR
4390         if (r_cg_permutation != perm)
4391         {
4392                 r_cg_permutation = perm;
4393                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4394                 {
4395                         if (!r_cg_permutation->compiled)
4396                                 R_CG_CompilePermutation(perm, mode, permutation);
4397                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4398                         {
4399                                 // remove features until we find a valid permutation
4400                                 int i;
4401                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4402                                 {
4403                                         // reduce i more quickly whenever it would not remove any bits
4404                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4405                                         if (!(permutation & j))
4406                                                 continue;
4407                                         permutation -= j;
4408                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4409                                         if (!r_cg_permutation->compiled)
4410                                                 R_CG_CompilePermutation(perm, mode, permutation);
4411                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4412                                                 break;
4413                                 }
4414                                 if (i >= SHADERPERMUTATION_COUNT)
4415                                 {
4416                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4417                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4418                                         return; // no bit left to clear, entire mode is broken
4419                                 }
4420                         }
4421                 }
4422                 CHECKGLERROR
4423                 CHECKCGERROR
4424                 if (r_cg_permutation->vprogram)
4425                 {
4426                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4427                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4428                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4429                 }
4430                 else
4431                 {
4432                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4433                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4434                 }
4435                 if (r_cg_permutation->fprogram)
4436                 {
4437                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4438                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4439                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4440                 }
4441                 else
4442                 {
4443                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4444                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4445                 }
4446         }
4447         CHECKCGERROR
4448         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4449         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4450         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4451 }
4452
4453 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4454 {
4455         cgGLSetTextureParameter(param, R_GetTexture(tex));
4456         cgGLEnableTextureParameter(param);
4457 }
4458 #endif
4459
4460 #ifdef SUPPORTD3D
4461
4462 #ifdef SUPPORTD3D
4463 #include <d3d9.h>
4464 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4465 extern D3DCAPS9 vid_d3d9caps;
4466 #endif
4467
4468 struct r_hlsl_permutation_s;
4469 typedef struct r_hlsl_permutation_s
4470 {
4471         /// hash lookup data
4472         struct r_hlsl_permutation_s *hashnext;
4473         unsigned int mode;
4474         unsigned int permutation;
4475
4476         /// indicates if we have tried compiling this permutation already
4477         qboolean compiled;
4478         /// NULL if compilation failed
4479         IDirect3DVertexShader9 *vertexshader;
4480         IDirect3DPixelShader9 *pixelshader;
4481 }
4482 r_hlsl_permutation_t;
4483
4484 typedef enum D3DVSREGISTER_e
4485 {
4486         D3DVSREGISTER_TexMatrix = 0, // float4x4
4487         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4488         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4489         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4490         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4491         D3DVSREGISTER_ModelToLight = 20, // float4x4
4492         D3DVSREGISTER_EyePosition = 24,
4493         D3DVSREGISTER_FogPlane = 25,
4494         D3DVSREGISTER_LightDir = 26,
4495         D3DVSREGISTER_LightPosition = 27,
4496 }
4497 D3DVSREGISTER_t;
4498
4499 typedef enum D3DPSREGISTER_e
4500 {
4501         D3DPSREGISTER_Alpha = 0,
4502         D3DPSREGISTER_BloomBlur_Parameters = 1,
4503         D3DPSREGISTER_ClientTime = 2,
4504         D3DPSREGISTER_Color_Ambient = 3,
4505         D3DPSREGISTER_Color_Diffuse = 4,
4506         D3DPSREGISTER_Color_Specular = 5,
4507         D3DPSREGISTER_Color_Glow = 6,
4508         D3DPSREGISTER_Color_Pants = 7,
4509         D3DPSREGISTER_Color_Shirt = 8,
4510         D3DPSREGISTER_DeferredColor_Ambient = 9,
4511         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4512         D3DPSREGISTER_DeferredColor_Specular = 11,
4513         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4514         D3DPSREGISTER_DeferredMod_Specular = 13,
4515         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4516         D3DPSREGISTER_EyePosition = 15, // unused
4517         D3DPSREGISTER_FogColor = 16,
4518         D3DPSREGISTER_FogHeightFade = 17,
4519         D3DPSREGISTER_FogPlane = 18,
4520         D3DPSREGISTER_FogPlaneViewDist = 19,
4521         D3DPSREGISTER_FogRangeRecip = 20,
4522         D3DPSREGISTER_LightColor = 21,
4523         D3DPSREGISTER_LightDir = 22, // unused
4524         D3DPSREGISTER_LightPosition = 23,
4525         D3DPSREGISTER_OffsetMapping_Scale = 24,
4526         D3DPSREGISTER_PixelSize = 25,
4527         D3DPSREGISTER_ReflectColor = 26,
4528         D3DPSREGISTER_ReflectFactor = 27,
4529         D3DPSREGISTER_ReflectOffset = 28,
4530         D3DPSREGISTER_RefractColor = 29,
4531         D3DPSREGISTER_Saturation = 30,
4532         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4533         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4534         D3DPSREGISTER_ScreenToDepth = 33,
4535         D3DPSREGISTER_ShadowMap_Parameters = 34,
4536         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4537         D3DPSREGISTER_SpecularPower = 36,
4538         D3DPSREGISTER_UserVec1 = 37,
4539         D3DPSREGISTER_UserVec2 = 38,
4540         D3DPSREGISTER_UserVec3 = 39,
4541         D3DPSREGISTER_UserVec4 = 40,
4542         D3DPSREGISTER_ViewTintColor = 41,
4543         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4544         D3DPSREGISTER_BloomColorSubtract = 43,
4545         D3DPSREGISTER_ViewToLight = 44, // float4x4
4546         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4547         D3DPSREGISTER_NormalmapScrollBlend = 52,
4548         // next at 53
4549 }
4550 D3DPSREGISTER_t;
4551
4552 /// information about each possible shader permutation
4553 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4554 /// currently selected permutation
4555 r_hlsl_permutation_t *r_hlsl_permutation;
4556 /// storage for permutations linked in the hash table
4557 memexpandablearray_t r_hlsl_permutationarray;
4558
4559 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4560 {
4561         //unsigned int hashdepth = 0;
4562         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4563         r_hlsl_permutation_t *p;
4564         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4565         {
4566                 if (p->mode == mode && p->permutation == permutation)
4567                 {
4568                         //if (hashdepth > 10)
4569                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4570                         return p;
4571                 }
4572                 //hashdepth++;
4573         }
4574         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4575         p->mode = mode;
4576         p->permutation = permutation;
4577         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4578         r_hlsl_permutationhash[mode][hashindex] = p;
4579         //if (hashdepth > 10)
4580         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4581         return p;
4582 }
4583
4584 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4585 {
4586         char *shaderstring;
4587         if (!filename || !filename[0])
4588                 return NULL;
4589         if (!strcmp(filename, "hlsl/default.hlsl"))
4590         {
4591                 if (!hlslshaderstring)
4592                 {
4593                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4594                         if (hlslshaderstring)
4595                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4596                         else
4597                                 hlslshaderstring = (char *)builtincgshaderstring;
4598                 }
4599                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4600                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4601                 return shaderstring;
4602         }
4603         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4604         if (shaderstring)
4605         {
4606                 if (printfromdisknotice)
4607                         Con_DPrintf("from disk %s... ", filename);
4608                 return shaderstring;
4609         }
4610         return shaderstring;
4611 }
4612
4613 #include <d3dx9.h>
4614 //#include <d3dx9shader.h>
4615 //#include <d3dx9mesh.h>
4616
4617 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4618 {
4619         DWORD *vsbin = NULL;
4620         DWORD *psbin = NULL;
4621         fs_offset_t vsbinsize;
4622         fs_offset_t psbinsize;
4623 //      IDirect3DVertexShader9 *vs = NULL;
4624 //      IDirect3DPixelShader9 *ps = NULL;
4625         ID3DXBuffer *vslog = NULL;
4626         ID3DXBuffer *vsbuffer = NULL;
4627         ID3DXConstantTable *vsconstanttable = NULL;
4628         ID3DXBuffer *pslog = NULL;
4629         ID3DXBuffer *psbuffer = NULL;
4630         ID3DXConstantTable *psconstanttable = NULL;
4631         int vsresult = 0;
4632         int psresult = 0;
4633         char temp[MAX_INPUTLINE];
4634         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4635         qboolean debugshader = gl_paranoid.integer != 0;
4636         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4637         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4638         if (!debugshader)
4639         {
4640                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4641                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4642         }
4643         if ((!vsbin && vertstring) || (!psbin && fragstring))
4644         {
4645                 const char* dllnames_d3dx9 [] =
4646                 {
4647                         "d3dx9_43.dll",
4648                         "d3dx9_42.dll",
4649                         "d3dx9_41.dll",
4650                         "d3dx9_40.dll",
4651                         "d3dx9_39.dll",
4652                         "d3dx9_38.dll",
4653                         "d3dx9_37.dll",
4654                         "d3dx9_36.dll",
4655                         "d3dx9_35.dll",
4656                         "d3dx9_34.dll",
4657                         "d3dx9_33.dll",
4658                         "d3dx9_32.dll",
4659                         "d3dx9_31.dll",
4660                         "d3dx9_30.dll",
4661                         "d3dx9_29.dll",
4662                         "d3dx9_28.dll",
4663                         "d3dx9_27.dll",
4664                         "d3dx9_26.dll",
4665                         "d3dx9_25.dll",
4666                         "d3dx9_24.dll",
4667                         NULL
4668                 };
4669                 dllhandle_t d3dx9_dll = NULL;
4670                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4671                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4672                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4673                 dllfunction_t d3dx9_dllfuncs[] =
4674                 {
4675                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4676                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4677                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4678                         {NULL, NULL}
4679                 };
4680                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4681                 {
4682                         DWORD shaderflags = 0;
4683                         if (debugshader)
4684                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4685                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4686                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4687                         if (vertstring && vertstring[0])
4688                         {
4689                                 if (debugshader)
4690                                 {
4691 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4692 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4693                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4694                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4695                                 }
4696                                 else
4697                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4698                                 if (vsbuffer)
4699                                 {
4700                                         vsbinsize = vsbuffer->GetBufferSize();
4701                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4702                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4703                                         vsbuffer->Release();
4704                                 }
4705                                 if (vslog)
4706                                 {
4707                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4708                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4709                                         vslog->Release();
4710                                 }
4711                         }
4712                         if (fragstring && fragstring[0])
4713                         {
4714                                 if (debugshader)
4715                                 {
4716 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4717 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4718                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4719                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4720                                 }
4721                                 else
4722                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4723                                 if (psbuffer)
4724                                 {
4725                                         psbinsize = psbuffer->GetBufferSize();
4726                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4727                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4728                                         psbuffer->Release();
4729                                 }
4730                                 if (pslog)
4731                                 {
4732                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4733                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4734                                         pslog->Release();
4735                                 }
4736                         }
4737                         Sys_UnloadLibrary(&d3dx9_dll);
4738                 }
4739                 else
4740                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4741         }
4742         if (vsbin && psbin)
4743         {
4744                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4745                 if (FAILED(vsresult))
4746                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4747                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4748                 if (FAILED(psresult))
4749                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4750         }
4751         // free the shader data
4752         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4753         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4754 }
4755
4756 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4757 {
4758         int i;
4759         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4760         int vertstring_length = 0;
4761         int geomstring_length = 0;
4762         int fragstring_length = 0;
4763         char *t;
4764         char *vertexstring, *geometrystring, *fragmentstring;
4765         char *vertstring, *geomstring, *fragstring;
4766         char permutationname[256];
4767         char cachename[256];
4768         int vertstrings_count = 0;
4769         int geomstrings_count = 0;
4770         int fragstrings_count = 0;
4771         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4772         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4773         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4774
4775         if (p->compiled)
4776                 return;
4777         p->compiled = true;
4778         p->vertexshader = NULL;
4779         p->pixelshader = NULL;
4780
4781         permutationname[0] = 0;
4782         cachename[0] = 0;
4783         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4784         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4785         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4786
4787         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4788         strlcat(cachename, "hlsl/", sizeof(cachename));
4789
4790         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4791         vertstrings_count = 0;
4792         geomstrings_count = 0;
4793         fragstrings_count = 0;
4794         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4795         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4796         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4797
4798         // the first pretext is which type of shader to compile as
4799         // (later these will all be bound together as a program object)
4800         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4801         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4802         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4803
4804         // the second pretext is the mode (for example a light source)
4805         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4806         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4807         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4808         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4809         strlcat(cachename, modeinfo->name, sizeof(cachename));
4810
4811         // now add all the permutation pretexts
4812         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4813         {
4814                 if (permutation & (1<<i))
4815                 {
4816                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4817                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4818                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4819                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4820                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4821                 }
4822                 else
4823                 {
4824                         // keep line numbers correct
4825                         vertstrings_list[vertstrings_count++] = "\n";
4826                         geomstrings_list[geomstrings_count++] = "\n";
4827                         fragstrings_list[fragstrings_count++] = "\n";
4828                 }
4829         }
4830
4831         // add static parms
4832         R_CompileShader_AddStaticParms(mode, permutation);
4833         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4834         vertstrings_count += shaderstaticparms_count;
4835         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4836         geomstrings_count += shaderstaticparms_count;
4837         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4838         fragstrings_count += shaderstaticparms_count;
4839
4840         // replace spaces in the cachename with _ characters
4841         for (i = 0;cachename[i];i++)
4842                 if (cachename[i] == ' ')
4843                         cachename[i] = '_';
4844
4845         // now append the shader text itself
4846         vertstrings_list[vertstrings_count++] = vertexstring;
4847         geomstrings_list[geomstrings_count++] = geometrystring;
4848         fragstrings_list[fragstrings_count++] = fragmentstring;
4849
4850         // if any sources were NULL, clear the respective list
4851         if (!vertexstring)
4852                 vertstrings_count = 0;
4853         if (!geometrystring)
4854                 geomstrings_count = 0;
4855         if (!fragmentstring)
4856                 fragstrings_count = 0;
4857
4858         vertstring_length = 0;
4859         for (i = 0;i < vertstrings_count;i++)
4860                 vertstring_length += strlen(vertstrings_list[i]);
4861         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4862         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4863                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4864
4865         geomstring_length = 0;
4866         for (i = 0;i < geomstrings_count;i++)
4867                 geomstring_length += strlen(geomstrings_list[i]);
4868         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4869         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4870                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4871
4872         fragstring_length = 0;
4873         for (i = 0;i < fragstrings_count;i++)
4874                 fragstring_length += strlen(fragstrings_list[i]);
4875         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4876         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4877                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4878
4879         // try to load the cached shader, or generate one
4880         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4881
4882         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4883                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4884         else
4885                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4886
4887         // free the strings
4888         if (vertstring)
4889                 Mem_Free(vertstring);
4890         if (geomstring)
4891                 Mem_Free(geomstring);
4892         if (fragstring)
4893                 Mem_Free(fragstring);
4894         if (vertexstring)
4895                 Mem_Free(vertexstring);
4896         if (geometrystring)
4897                 Mem_Free(geometrystring);
4898         if (fragmentstring)
4899                 Mem_Free(fragmentstring);
4900 }
4901
4902 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4903 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4904 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4905 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4906 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4907 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4908
4909 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4910 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4911 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4912 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4913 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4914 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4915
4916 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4917 {
4918         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4919         if (r_hlsl_permutation != perm)
4920         {
4921                 r_hlsl_permutation = perm;
4922                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4923                 {
4924                         if (!r_hlsl_permutation->compiled)
4925                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4926                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4927                         {
4928                                 // remove features until we find a valid permutation
4929                                 int i;
4930                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4931                                 {
4932                                         // reduce i more quickly whenever it would not remove any bits
4933                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4934                                         if (!(permutation & j))
4935                                                 continue;
4936                                         permutation -= j;
4937                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4938                                         if (!r_hlsl_permutation->compiled)
4939                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4940                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4941                                                 break;
4942                                 }
4943                                 if (i >= SHADERPERMUTATION_COUNT)
4944                                 {
4945                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4946                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4947                                         return; // no bit left to clear, entire mode is broken
4948                                 }
4949                         }
4950                 }
4951                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4952                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4953         }
4954         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4955         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4956         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4957 }
4958 #endif
4959
4960 void R_GLSL_Restart_f(void)
4961 {
4962         unsigned int i, limit;
4963         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4964                 Mem_Free(glslshaderstring);
4965         glslshaderstring = NULL;
4966         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4967                 Mem_Free(cgshaderstring);
4968         cgshaderstring = NULL;
4969         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4970                 Mem_Free(hlslshaderstring);
4971         hlslshaderstring = NULL;
4972         switch(vid.renderpath)
4973         {
4974         case RENDERPATH_D3D9:
4975 #ifdef SUPPORTD3D
4976                 {
4977                         r_hlsl_permutation_t *p;
4978                         r_hlsl_permutation = NULL;
4979 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4980 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4981 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4982 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4983                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4984                         for (i = 0;i < limit;i++)
4985                         {
4986                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4987                                 {
4988                                         if (p->vertexshader)
4989                                                 IDirect3DVertexShader9_Release(p->vertexshader);
4990                                         if (p->pixelshader)
4991                                                 IDirect3DPixelShader9_Release(p->pixelshader);
4992                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4993                                 }
4994                         }
4995                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4996                 }
4997 #endif
4998                 break;
4999         case RENDERPATH_D3D10:
5000                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5001                 break;
5002         case RENDERPATH_D3D11:
5003                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5004                 break;
5005         case RENDERPATH_GL20:
5006                 {
5007                         r_glsl_permutation_t *p;
5008                         r_glsl_permutation = NULL;
5009                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
5010                         for (i = 0;i < limit;i++)
5011                         {
5012                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
5013                                 {
5014                                         GL_Backend_FreeProgram(p->program);
5015                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5016                                 }
5017                         }
5018                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5019                 }
5020                 break;
5021         case RENDERPATH_CGGL:
5022 #ifdef SUPPORTCG
5023                 {
5024                         r_cg_permutation_t *p;
5025                         r_cg_permutation = NULL;
5026                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5027                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5028                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5029                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5030                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5031                         for (i = 0;i < limit;i++)
5032                         {
5033                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5034                                 {
5035                                         if (p->vprogram)
5036                                                 cgDestroyProgram(p->vprogram);
5037                                         if (p->fprogram)
5038                                                 cgDestroyProgram(p->fprogram);
5039                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5040                                 }
5041                         }
5042                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5043                 }
5044 #endif
5045                 break;
5046         case RENDERPATH_GL13:
5047         case RENDERPATH_GL11:
5048                 break;
5049         }
5050 }
5051
5052 void R_GLSL_DumpShader_f(void)
5053 {
5054         int i;
5055         qfile_t *file;
5056
5057         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5058         if (file)
5059         {
5060                 FS_Print(file, "/* The engine may define the following macros:\n");
5061                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5062                 for (i = 0;i < SHADERMODE_COUNT;i++)
5063                         FS_Print(file, glslshadermodeinfo[i].pretext);
5064                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5065                         FS_Print(file, shaderpermutationinfo[i].pretext);
5066                 FS_Print(file, "*/\n");
5067                 FS_Print(file, builtinshaderstring);
5068                 FS_Close(file);
5069                 Con_Printf("glsl/default.glsl written\n");
5070         }
5071         else
5072                 Con_Printf("failed to write to glsl/default.glsl\n");
5073
5074 #ifdef SUPPORTCG
5075         file = FS_OpenRealFile("cg/default.cg", "w", false);
5076         if (file)
5077         {
5078                 FS_Print(file, "/* The engine may define the following macros:\n");
5079                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5080                 for (i = 0;i < SHADERMODE_COUNT;i++)
5081                         FS_Print(file, cgshadermodeinfo[i].pretext);
5082                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5083                         FS_Print(file, shaderpermutationinfo[i].pretext);
5084                 FS_Print(file, "*/\n");
5085                 FS_Print(file, builtincgshaderstring);
5086                 FS_Close(file);
5087                 Con_Printf("cg/default.cg written\n");
5088         }
5089         else
5090                 Con_Printf("failed to write to cg/default.cg\n");
5091 #endif
5092
5093 #ifdef SUPPORTD3D
5094         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5095         if (file)
5096         {
5097                 FS_Print(file, "/* The engine may define the following macros:\n");
5098                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5099                 for (i = 0;i < SHADERMODE_COUNT;i++)
5100                         FS_Print(file, hlslshadermodeinfo[i].pretext);
5101                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5102                         FS_Print(file, shaderpermutationinfo[i].pretext);
5103                 FS_Print(file, "*/\n");
5104                 FS_Print(file, builtincgshaderstring);
5105                 FS_Close(file);
5106                 Con_Printf("hlsl/default.hlsl written\n");
5107         }
5108         else
5109                 Con_Printf("failed to write to hlsl/default.hlsl\n");
5110 #endif
5111 }
5112
5113 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5114 {
5115         if (!second)
5116                 texturemode = GL_MODULATE;
5117         switch (vid.renderpath)
5118         {
5119         case RENDERPATH_D3D9:
5120 #ifdef SUPPORTD3D
5121                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5122                 R_Mesh_TexBind(GL20TU_FIRST , first );
5123                 R_Mesh_TexBind(GL20TU_SECOND, second);
5124 #endif
5125                 break;
5126         case RENDERPATH_D3D10:
5127                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5128                 break;
5129         case RENDERPATH_D3D11:
5130                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5131                 break;
5132         case RENDERPATH_GL20:
5133                 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))));
5134                 R_Mesh_TexBind(GL20TU_FIRST , first );
5135                 R_Mesh_TexBind(GL20TU_SECOND, second);
5136                 break;
5137         case RENDERPATH_CGGL:
5138 #ifdef SUPPORTCG
5139                 CHECKCGERROR
5140                 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))));
5141                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5142                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5143 #endif
5144                 break;
5145         case RENDERPATH_GL13:
5146                 R_Mesh_TexBind(0, first );
5147                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5148                 R_Mesh_TexBind(1, second);
5149                 if (second)
5150                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5151                 break;
5152         case RENDERPATH_GL11:
5153                 R_Mesh_TexBind(0, first );
5154                 break;
5155         }
5156 }
5157
5158 void R_SetupShader_DepthOrShadow(void)
5159 {
5160         switch (vid.renderpath)
5161         {
5162         case RENDERPATH_D3D9:
5163 #ifdef SUPPORTD3D
5164                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5165 #endif
5166                 break;
5167         case RENDERPATH_D3D10:
5168                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5169                 break;
5170         case RENDERPATH_D3D11:
5171                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5172                 break;
5173         case RENDERPATH_GL20:
5174                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5175                 break;
5176         case RENDERPATH_CGGL:
5177 #ifdef SUPPORTCG
5178                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5179 #endif
5180                 break;
5181         case RENDERPATH_GL13:
5182                 R_Mesh_TexBind(0, 0);
5183                 R_Mesh_TexBind(1, 0);
5184                 break;
5185         case RENDERPATH_GL11:
5186                 R_Mesh_TexBind(0, 0);
5187                 break;
5188         }
5189 }
5190
5191 void R_SetupShader_ShowDepth(void)
5192 {
5193         switch (vid.renderpath)
5194         {
5195         case RENDERPATH_D3D9:
5196 #ifdef SUPPORTHLSL
5197                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5198 #endif
5199                 break;
5200         case RENDERPATH_D3D10:
5201                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5202                 break;
5203         case RENDERPATH_D3D11:
5204                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5205                 break;
5206         case RENDERPATH_GL20:
5207                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5208                 break;
5209         case RENDERPATH_CGGL:
5210 #ifdef SUPPORTCG
5211                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5212 #endif
5213                 break;
5214         case RENDERPATH_GL13:
5215                 break;
5216         case RENDERPATH_GL11:
5217                 break;
5218         }
5219 }
5220
5221 extern qboolean r_shadow_usingdeferredprepass;
5222 extern cvar_t r_shadow_deferred_8bitrange;
5223 extern rtexture_t *r_shadow_attenuationgradienttexture;
5224 extern rtexture_t *r_shadow_attenuation2dtexture;
5225 extern rtexture_t *r_shadow_attenuation3dtexture;
5226 extern qboolean r_shadow_usingshadowmap2d;
5227 extern qboolean r_shadow_usingshadowmaportho;
5228 extern float r_shadow_shadowmap_texturescale[2];
5229 extern float r_shadow_shadowmap_parameters[4];
5230 extern qboolean r_shadow_shadowmapvsdct;
5231 extern qboolean r_shadow_shadowmapsampler;
5232 extern int r_shadow_shadowmappcf;
5233 extern rtexture_t *r_shadow_shadowmap2dtexture;
5234 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5235 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5236 extern matrix4x4_t r_shadow_shadowmapmatrix;
5237 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5238 extern int r_shadow_prepass_width;
5239 extern int r_shadow_prepass_height;
5240 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5241 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5242 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5243 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5244 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5245 extern cvar_t gl_mesh_separatearrays;
5246 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5247 {
5248         // a blendfunc allows colormod if:
5249         // a) it can never keep the destination pixel invariant, or
5250         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5251         // this is to prevent unintended side effects from colormod
5252
5253         // in formulas:
5254         // IF there is a (s, sa) for which for all (d, da),
5255         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5256         // THEN, for this (s, sa) and all (colormod, d, da):
5257         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5258         // OBVIOUSLY, this means that
5259         //   s*colormod * src(s*colormod, d, sa, da) = 0
5260         //   dst(s*colormod, d, sa, da)              = 1
5261
5262         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5263
5264         // main condition to leave dst color invariant:
5265         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5266         //   src == GL_ZERO:
5267         //     s * 0 + d * dst(s, d, sa, da) == d
5268         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5269         //       => colormod is a problem for GL_SRC_COLOR only
5270         //   src == GL_ONE:
5271         //     s + d * dst(s, d, sa, da) == d
5272         //       => s == 0
5273         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5274         //       => colormod is never problematic for these
5275         //   src == GL_SRC_COLOR:
5276         //     s*s + d * dst(s, d, sa, da) == d
5277         //       => s == 0
5278         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5279         //       => colormod is never problematic for these
5280         //   src == GL_ONE_MINUS_SRC_COLOR:
5281         //     s*(1-s) + d * dst(s, d, sa, da) == d
5282         //       => s == 0 or s == 1
5283         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5284         //       => colormod is a problem for GL_SRC_COLOR only
5285         //   src == GL_DST_COLOR
5286         //     s*d + d * dst(s, d, sa, da) == d
5287         //       => s == 1
5288         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5289         //       => colormod is always a problem
5290         //     or
5291         //       => s == 0
5292         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5293         //       => colormod is never problematic for these
5294         //       => BUT, we do not know s! We must assume it is problematic
5295         //       then... except in GL_ONE case, where we know all invariant
5296         //       cases are fine
5297         //   src == GL_ONE_MINUS_DST_COLOR
5298         //     s*(1-d) + d * dst(s, d, sa, da) == d
5299         //       => s == 0 (1-d is impossible to handle for our desired result)
5300         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5301         //       => colormod is never problematic for these
5302         //   src == GL_SRC_ALPHA
5303         //     s*sa + d * dst(s, d, sa, da) == d
5304         //       => s == 0, or sa == 0
5305         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5306         //       => colormod breaks in the case GL_SRC_COLOR only
5307         //   src == GL_ONE_MINUS_SRC_ALPHA
5308         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5309         //       => s == 0, or sa == 1
5310         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5311         //       => colormod breaks in the case GL_SRC_COLOR only
5312         //   src == GL_DST_ALPHA
5313         //     s*da + d * dst(s, d, sa, da) == d
5314         //       => s == 0
5315         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5316         //       => colormod is never problematic for these
5317
5318         switch(src)
5319         {
5320                 case GL_ZERO:
5321                 case GL_ONE_MINUS_SRC_COLOR:
5322                 case GL_SRC_ALPHA:
5323                 case GL_ONE_MINUS_SRC_ALPHA:
5324                         if(dst == GL_SRC_COLOR)
5325                                 return false;
5326                         return true;
5327                 case GL_ONE:
5328                 case GL_SRC_COLOR:
5329                 case GL_ONE_MINUS_DST_COLOR:
5330                 case GL_DST_ALPHA:
5331                 case GL_ONE_MINUS_DST_ALPHA:
5332                         return true;
5333                 case GL_DST_COLOR:
5334                         if(dst == GL_ONE)
5335                                 return true;
5336                         return false;
5337                 default:
5338                         return false;
5339         }
5340 }
5341 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane)
5342 {
5343         // select a permutation of the lighting shader appropriate to this
5344         // combination of texture, entity, light source, and fogging, only use the
5345         // minimum features necessary to avoid wasting rendering time in the
5346         // fragment shader on features that are not being used
5347         unsigned int permutation = 0;
5348         unsigned int mode = 0;
5349         qboolean allow_colormod;
5350         static float dummy_colormod[3] = {1, 1, 1};
5351         float *colormod = rsurface.colormod;
5352         float m16f[16];
5353         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5354         if (rsurfacepass == RSURFPASS_BACKGROUND)
5355         {
5356                 // distorted background
5357                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5358                 {
5359                         mode = SHADERMODE_WATER;
5360                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
5361                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
5362                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5363                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5364                 }
5365                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5366                 {
5367                         mode = SHADERMODE_REFRACTION;
5368                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5369                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5370                 }
5371                 else
5372                 {
5373                         mode = SHADERMODE_GENERIC;
5374                         permutation |= SHADERPERMUTATION_DIFFUSE;
5375                         GL_BlendFunc(GL_ONE, GL_ZERO);
5376                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5377                 }
5378                 GL_AlphaTest(false);
5379         }
5380         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5381         {
5382                 if (r_glsl_offsetmapping.integer)
5383                 {
5384                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5385                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5386                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5387                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5388                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5389                         {
5390                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5391                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5392                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5393                         }
5394                 }
5395                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5396                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5397                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5398                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5399                 // normalmap (deferred prepass), may use alpha test on diffuse
5400                 mode = SHADERMODE_DEFERREDGEOMETRY;
5401                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5402                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5403                 GL_AlphaTest(false);
5404                 GL_BlendFunc(GL_ONE, GL_ZERO);
5405                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5406         }
5407         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5408         {
5409                 if (r_glsl_offsetmapping.integer)
5410                 {
5411                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5412                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5413                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5414                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5415                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5416                         {
5417                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5418                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5419                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5420                         }
5421                 }
5422                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5423                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5424                 // light source
5425                 mode = SHADERMODE_LIGHTSOURCE;
5426                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5427                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5428                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5429                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5430                 if (diffusescale > 0)
5431                         permutation |= SHADERPERMUTATION_DIFFUSE;
5432                 if (specularscale > 0)
5433                 {
5434                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5435                         if (r_shadow_glossexact.integer)
5436                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5437                 }
5438                 if (r_refdef.fogenabled)
5439                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5440                 if (rsurface.texture->colormapping)
5441                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5442                 if (r_shadow_usingshadowmap2d)
5443                 {
5444                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5445                         if(r_shadow_shadowmapvsdct)
5446                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5447
5448                         if (r_shadow_shadowmapsampler)
5449                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5450                         if (r_shadow_shadowmappcf > 1)
5451                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5452                         else if (r_shadow_shadowmappcf)
5453                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5454                 }
5455                 if (rsurface.texture->reflectmasktexture)
5456                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5457                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5458                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5459                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5460         }
5461         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5462         {
5463                 if (r_glsl_offsetmapping.integer)
5464                 {
5465                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5466                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5467                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5468                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5469                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5470                         {
5471                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5472                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5473                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5474                         }
5475                 }
5476                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5477                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5478                 // unshaded geometry (fullbright or ambient model lighting)
5479                 mode = SHADERMODE_FLATCOLOR;
5480                 ambientscale = diffusescale = specularscale = 0;
5481                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5482                         permutation |= SHADERPERMUTATION_GLOW;
5483                 if (r_refdef.fogenabled)
5484                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5485                 if (rsurface.texture->colormapping)
5486                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5487                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5488                 {
5489                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5490                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5491
5492                         if (r_shadow_shadowmapsampler)
5493                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5494                         if (r_shadow_shadowmappcf > 1)
5495                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5496                         else if (r_shadow_shadowmappcf)
5497                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5498                 }
5499                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5500                         permutation |= SHADERPERMUTATION_REFLECTION;
5501                 if (rsurface.texture->reflectmasktexture)
5502                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5503                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5504                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5505                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5506         }
5507         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5508         {
5509                 if (r_glsl_offsetmapping.integer)
5510                 {
5511                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5512                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5513                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5514                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5515                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5516                         {
5517                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5518                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5519                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5520                         }
5521                 }
5522                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5523                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5524                 // directional model lighting
5525                 mode = SHADERMODE_LIGHTDIRECTION;
5526                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5527                         permutation |= SHADERPERMUTATION_GLOW;
5528                 permutation |= SHADERPERMUTATION_DIFFUSE;
5529                 if (specularscale > 0)
5530                 {
5531                         permutation |= SHADERPERMUTATION_SPECULAR;
5532                         if (r_shadow_glossexact.integer)
5533                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5534                 }
5535                 if (r_refdef.fogenabled)
5536                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5537                 if (rsurface.texture->colormapping)
5538                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5539                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5540                 {
5541                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5542                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5543
5544                         if (r_shadow_shadowmapsampler)
5545                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5546                         if (r_shadow_shadowmappcf > 1)
5547                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5548                         else if (r_shadow_shadowmappcf)
5549                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5550                 }
5551                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5552                         permutation |= SHADERPERMUTATION_REFLECTION;
5553                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5554                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5555                 if (rsurface.texture->reflectmasktexture)
5556                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5557                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5558                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5559                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5560         }
5561         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5562         {
5563                 if (r_glsl_offsetmapping.integer)
5564                 {
5565                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5566                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5567                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5568                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5569                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5570                         {
5571                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5572                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5573                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5574                         }
5575                 }
5576                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5577                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5578                 // ambient model lighting
5579                 mode = SHADERMODE_LIGHTDIRECTION;
5580                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5581                         permutation |= SHADERPERMUTATION_GLOW;
5582                 if (r_refdef.fogenabled)
5583                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5584                 if (rsurface.texture->colormapping)
5585                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5586                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5587                 {
5588                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5589                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5590
5591                         if (r_shadow_shadowmapsampler)
5592                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5593                         if (r_shadow_shadowmappcf > 1)
5594                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5595                         else if (r_shadow_shadowmappcf)
5596                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5597                 }
5598                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5599                         permutation |= SHADERPERMUTATION_REFLECTION;
5600                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5601                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5602                 if (rsurface.texture->reflectmasktexture)
5603                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5604                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5605                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5606                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5607         }
5608         else
5609         {
5610                 if (r_glsl_offsetmapping.integer)
5611                 {
5612                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5613                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5614                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5615                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5616                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5617                         {
5618                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5619                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5620                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5621                         }
5622                 }
5623                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5624                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5625                 // lightmapped wall
5626                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5627                         permutation |= SHADERPERMUTATION_GLOW;
5628                 if (r_refdef.fogenabled)
5629                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5630                 if (rsurface.texture->colormapping)
5631                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5632                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5633                 {
5634                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5635                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5636
5637                         if (r_shadow_shadowmapsampler)
5638                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5639                         if (r_shadow_shadowmappcf > 1)
5640                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5641                         else if (r_shadow_shadowmappcf)
5642                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5643                 }
5644                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5645                         permutation |= SHADERPERMUTATION_REFLECTION;
5646                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5647                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5648                 if (rsurface.texture->reflectmasktexture)
5649                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5650                 if (FAKELIGHT_ENABLED)
5651                 {
5652                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5653                         mode = SHADERMODE_FAKELIGHT;
5654                         permutation |= SHADERPERMUTATION_DIFFUSE;
5655                         if (specularscale > 0)
5656                         {
5657                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5658                                 if (r_shadow_glossexact.integer)
5659                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5660                         }
5661                 }
5662                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5663                 {
5664                         // deluxemapping (light direction texture)
5665                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5666                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5667                         else
5668                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5669                         permutation |= SHADERPERMUTATION_DIFFUSE;
5670                         if (specularscale > 0)
5671                         {
5672                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5673                                 if (r_shadow_glossexact.integer)
5674                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5675                         }
5676                 }
5677                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5678                 {
5679                         // fake deluxemapping (uniform light direction in tangentspace)
5680                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5681                         permutation |= SHADERPERMUTATION_DIFFUSE;
5682                         if (specularscale > 0)
5683                         {
5684                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5685                                 if (r_shadow_glossexact.integer)
5686                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5687                         }
5688                 }
5689                 else if (rsurface.uselightmaptexture)
5690                 {
5691                         // ordinary lightmapping (q1bsp, q3bsp)
5692                         mode = SHADERMODE_LIGHTMAP;
5693                 }
5694                 else
5695                 {
5696                         // ordinary vertex coloring (q3bsp)
5697                         mode = SHADERMODE_VERTEXCOLOR;
5698                 }
5699                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5700                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5701                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5702         }
5703         if(!allow_colormod)
5704                 colormod = dummy_colormod;
5705         switch(vid.renderpath)
5706         {
5707         case RENDERPATH_D3D9:
5708 #ifdef SUPPORTD3D
5709                 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5710                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5711                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5712                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5713                 if (mode == SHADERMODE_LIGHTSOURCE)
5714                 {
5715                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5716                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5717                 }
5718                 else
5719                 {
5720                         if (mode == SHADERMODE_LIGHTDIRECTION)                                   
5721                         {
5722                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5723                         }
5724                 }
5725                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5726                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5727                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5728                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5729                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5730
5731                 if (mode == SHADERMODE_LIGHTSOURCE)
5732                 {
5733                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5734                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5735                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5736                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5737                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5738
5739                         // additive passes are only darkened by fog, not tinted
5740                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5741                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5742                 }
5743                 else
5744                 {
5745                         if (mode == SHADERMODE_FLATCOLOR)
5746                         {
5747                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5748                         }
5749                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5750                         {
5751                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
5752                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5753                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5754                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5755                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5756                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5757                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5758                         }
5759                         else
5760                         {
5761                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5762                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5763                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5764                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5765                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5766                         }
5767                         // additive passes are only darkened by fog, not tinted
5768                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5769                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5770                         else
5771                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5772                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
5773                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5774                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5775                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5776                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5777                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5778                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5779                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5780                         if (mode == SHADERMODE_WATER)
5781                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5782                 }
5783                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5784                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5785                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5786                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
5787                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5788                 if (rsurface.texture->pantstexture)
5789                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5790                 else
5791                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5792                 if (rsurface.texture->shirttexture)
5793                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5794                 else
5795                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5796                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5797                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5798                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5799                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5800                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5801                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5802                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5803
5804                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5805                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5806                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5807                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5808                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5809                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5810                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5811                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5812                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5813                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5814                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5815                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5816                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5817                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5818                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5819                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5820                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5821                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5822                 {
5823                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5824                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5825                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5826                 }
5827                 else
5828                 {
5829                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5830                 }
5831 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5832 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5833                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5834                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5835                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5836                 {
5837                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5838                         if (rsurface.rtlight)
5839                         {
5840                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5841                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5842                         }
5843                 }
5844 #endif
5845                 break;
5846         case RENDERPATH_D3D10:
5847                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5848                 break;
5849         case RENDERPATH_D3D11:
5850                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5851                 break;
5852         case RENDERPATH_GL20:
5853                 if (gl_mesh_separatearrays.integer)
5854                 {
5855                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5856                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5857                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5858                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5859                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5860                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5861                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5862                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5863                 }
5864                 else
5865                 {
5866                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5867                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5868                 }
5869                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5870                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5871                 if (mode == SHADERMODE_LIGHTSOURCE)
5872                 {
5873                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5874                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5875                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5876                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5877                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5878                         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);
5879         
5880                         // additive passes are only darkened by fog, not tinted
5881                         if (r_glsl_permutation->loc_FogColor >= 0)
5882                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5883                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5884                 }
5885                 else
5886                 {
5887                         if (mode == SHADERMODE_FLATCOLOR)
5888                         {
5889                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5890                         }
5891                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5892                         {
5893                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
5894                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5895                                 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);
5896                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5897                                 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);
5898                                 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]);
5899                                 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]);
5900                         }
5901                         else
5902                         {
5903                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5904                                 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]);
5905                                 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);
5906                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5907                                 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);
5908                         }
5909                         // additive passes are only darkened by fog, not tinted
5910                         if (r_glsl_permutation->loc_FogColor >= 0)
5911                         {
5912                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5913                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5914                                 else
5915                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5916                         }
5917                         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);
5918                         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]);
5919                         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]);
5920                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5921                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5922                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5923                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5924                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5925                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2fARB(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5926                 }
5927                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5928                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5929                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5930                 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]);
5931                 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]);
5932
5933                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5934                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
5935                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5936                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5937                 {
5938                         if (rsurface.texture->pantstexture)
5939                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5940                         else
5941                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5942                 }
5943                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5944                 {
5945                         if (rsurface.texture->shirttexture)
5946                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5947                         else
5948                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5949                 }
5950                 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]);
5951                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5952                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5953                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5954                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5955                 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]);
5956                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5957
5958         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5959         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5960         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5961                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5962                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5963                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5964                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5965                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5966                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5967                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5968                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5969                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5970                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5971                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5972                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5973                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5974                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5975                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5976                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5977                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5978                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5979                 {
5980                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5981                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5982                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5983                 }
5984                 else
5985                 {
5986                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5987                 }
5988 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5989 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5990                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5991                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5992                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5993                 {
5994                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5995                         if (rsurface.rtlight)
5996                         {
5997                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5998                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5999                         }
6000                 }
6001                 CHECKGLERROR
6002                 break;
6003         case RENDERPATH_CGGL:
6004 #ifdef SUPPORTCG
6005                 if (gl_mesh_separatearrays.integer)
6006                 {
6007                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
6008                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
6009                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
6010                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
6011                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
6012                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6013                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6014                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6015                 }
6016                 else
6017                 {
6018                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
6019                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6020                 }
6021                 R_SetupShader_SetPermutationCG(mode, permutation);
6022                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6023                 if (mode == SHADERMODE_LIGHTSOURCE)
6024                 {
6025                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6026                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6027                 }
6028                 else
6029                 {
6030                         if (mode == SHADERMODE_LIGHTDIRECTION)
6031                         {
6032                                 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
6033                         }
6034                 }
6035                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6036                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6037                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6038                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6039                 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
6040                 CHECKGLERROR
6041
6042                 if (mode == SHADERMODE_LIGHTSOURCE)
6043                 {
6044                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6045                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6046                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6047                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6048                         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
6049
6050                         // additive passes are only darkened by fog, not tinted
6051                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6052                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6053                 }
6054                 else
6055                 {
6056                         if (mode == SHADERMODE_FLATCOLOR)
6057                         {
6058                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6059                         }
6060                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6061                         {
6062                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);CHECKCGERROR
6063                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);CHECKCGERROR
6064                                 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
6065                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6066                                 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
6067                                 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
6068                                 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
6069                         }
6070                         else
6071                         {
6072                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);CHECKCGERROR
6073                                 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
6074                                 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
6075                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6076                                 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
6077                         }
6078                         // additive passes are only darkened by fog, not tinted
6079                         if (r_cg_permutation->fp_FogColor)
6080                         {
6081                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6082                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6083                                 else
6084                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6085                                 CHECKCGERROR
6086                         }
6087                         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
6088                         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
6089                         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
6090                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);CHECKCGERROR
6091                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);CHECKCGERROR
6092                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6093                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6094                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6095                         if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6096                 }
6097                 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
6098                 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
6099                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6100                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));CHECKCGERROR
6101                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6102                 if (r_cg_permutation->fp_Color_Pants)
6103                 {
6104                         if (rsurface.texture->pantstexture)
6105                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6106                         else
6107                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6108                         CHECKCGERROR
6109                 }
6110                 if (r_cg_permutation->fp_Color_Shirt)
6111                 {
6112                         if (rsurface.texture->shirttexture)
6113                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6114                         else
6115                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6116                         CHECKCGERROR
6117                 }
6118                 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
6119                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6120                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6121                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6122                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6123                 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
6124                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6125
6126         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
6127         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
6128         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
6129                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
6130                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
6131                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
6132                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
6133                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
6134                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
6135                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
6136                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
6137                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
6138                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
6139                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
6140                 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
6141                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
6142                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
6143                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6144                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6145                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6146                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6147                 {
6148                         if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);CHECKCGERROR
6149                         else if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);CHECKCGERROR
6150                         if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);CHECKCGERROR
6151                 }
6152                 else
6153                 {
6154                         if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);CHECKCGERROR
6155                 }
6156                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6157                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6158                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
6159                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
6160                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6161                 {
6162                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6163                         if (rsurface.rtlight)
6164                         {
6165                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6166                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6167                         }
6168                 }
6169
6170                 CHECKGLERROR
6171 #endif
6172                 break;
6173         case RENDERPATH_GL13:
6174         case RENDERPATH_GL11:
6175                 break;
6176         }
6177 }
6178
6179 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6180 {
6181         // select a permutation of the lighting shader appropriate to this
6182         // combination of texture, entity, light source, and fogging, only use the
6183         // minimum features necessary to avoid wasting rendering time in the
6184         // fragment shader on features that are not being used
6185         unsigned int permutation = 0;
6186         unsigned int mode = 0;
6187         const float *lightcolorbase = rtlight->currentcolor;
6188         float ambientscale = rtlight->ambientscale;
6189         float diffusescale = rtlight->diffusescale;
6190         float specularscale = rtlight->specularscale;
6191         // this is the location of the light in view space
6192         vec3_t viewlightorigin;
6193         // this transforms from view space (camera) to light space (cubemap)
6194         matrix4x4_t viewtolight;
6195         matrix4x4_t lighttoview;
6196         float viewtolight16f[16];
6197         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6198         // light source
6199         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6200         if (rtlight->currentcubemap != r_texture_whitecube)
6201                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6202         if (diffusescale > 0)
6203                 permutation |= SHADERPERMUTATION_DIFFUSE;
6204         if (specularscale > 0)
6205         {
6206                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6207                 if (r_shadow_glossexact.integer)
6208                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
6209         }
6210         if (r_shadow_usingshadowmap2d)
6211         {
6212                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6213                 if (r_shadow_shadowmapvsdct)
6214                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6215
6216                 if (r_shadow_shadowmapsampler)
6217                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6218                 if (r_shadow_shadowmappcf > 1)
6219                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6220                 else if (r_shadow_shadowmappcf)
6221                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6222         }
6223         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6224         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6225         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6226         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6227         switch(vid.renderpath)
6228         {
6229         case RENDERPATH_D3D9:
6230 #ifdef SUPPORTD3D
6231                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6232                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6233                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6234                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6235                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6236                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6237                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6238                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6239                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6240                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6241                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6242
6243                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6244                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
6245                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6246                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6247                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
6248                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6249 #endif
6250                 break;
6251         case RENDERPATH_D3D10:
6252                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6253                 break;
6254         case RENDERPATH_D3D11:
6255                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6256                 break;
6257         case RENDERPATH_GL20:
6258                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6259                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6260                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6261                 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);
6262                 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);
6263                 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);
6264                 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]);
6265                 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]);
6266                 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));
6267                 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]);
6268                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6269
6270                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6271                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6272                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6273                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6274                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6275                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6276                 break;
6277         case RENDERPATH_CGGL:
6278 #ifdef SUPPORTCG
6279                 R_SetupShader_SetPermutationCG(mode, permutation);
6280                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6281                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6282                 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
6283                 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
6284                 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
6285                 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
6286                 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
6287                 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
6288                 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
6289                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6290
6291                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6292                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6293                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6294                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6295                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6296                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6297 #endif
6298                 break;
6299         case RENDERPATH_GL13:
6300         case RENDERPATH_GL11:
6301                 break;
6302         }
6303 }
6304
6305 #define SKINFRAME_HASH 1024
6306
6307 typedef struct
6308 {
6309         int loadsequence; // incremented each level change
6310         memexpandablearray_t array;
6311         skinframe_t *hash[SKINFRAME_HASH];
6312 }
6313 r_skinframe_t;
6314 r_skinframe_t r_skinframe;
6315
6316 void R_SkinFrame_PrepareForPurge(void)
6317 {
6318         r_skinframe.loadsequence++;
6319         // wrap it without hitting zero
6320         if (r_skinframe.loadsequence >= 200)
6321                 r_skinframe.loadsequence = 1;
6322 }
6323
6324 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6325 {
6326         if (!skinframe)
6327                 return;
6328         // mark the skinframe as used for the purging code
6329         skinframe->loadsequence = r_skinframe.loadsequence;
6330 }
6331
6332 void R_SkinFrame_Purge(void)
6333 {
6334         int i;
6335         skinframe_t *s;
6336         for (i = 0;i < SKINFRAME_HASH;i++)
6337         {
6338                 for (s = r_skinframe.hash[i];s;s = s->next)
6339                 {
6340                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6341                         {
6342                                 if (s->merged == s->base)
6343                                         s->merged = NULL;
6344                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6345                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6346                                 R_PurgeTexture(s->merged);s->merged = NULL;
6347                                 R_PurgeTexture(s->base  );s->base   = NULL;
6348                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6349                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6350                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6351                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6352                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6353                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6354                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6355                                 s->loadsequence = 0;
6356                         }
6357                 }
6358         }
6359 }
6360
6361 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6362         skinframe_t *item;
6363         char basename[MAX_QPATH];
6364
6365         Image_StripImageExtension(name, basename, sizeof(basename));
6366
6367         if( last == NULL ) {
6368                 int hashindex;
6369                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6370                 item = r_skinframe.hash[hashindex];
6371         } else {
6372                 item = last->next;
6373         }
6374
6375         // linearly search through the hash bucket
6376         for( ; item ; item = item->next ) {
6377                 if( !strcmp( item->basename, basename ) ) {
6378                         return item;
6379                 }
6380         }
6381         return NULL;
6382 }
6383
6384 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6385 {
6386         skinframe_t *item;
6387         int hashindex;
6388         char basename[MAX_QPATH];
6389
6390         Image_StripImageExtension(name, basename, sizeof(basename));
6391
6392         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6393         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6394                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6395                         break;
6396
6397         if (!item) {
6398                 rtexture_t *dyntexture;
6399                 // check whether its a dynamic texture
6400                 dyntexture = CL_GetDynTexture( basename );
6401                 if (!add && !dyntexture)
6402                         return NULL;
6403                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6404                 memset(item, 0, sizeof(*item));
6405                 strlcpy(item->basename, basename, sizeof(item->basename));
6406                 item->base = dyntexture; // either NULL or dyntexture handle
6407                 item->textureflags = textureflags;
6408                 item->comparewidth = comparewidth;
6409                 item->compareheight = compareheight;
6410                 item->comparecrc = comparecrc;
6411                 item->next = r_skinframe.hash[hashindex];
6412                 r_skinframe.hash[hashindex] = item;
6413         }
6414         else if( item->base == NULL )
6415         {
6416                 rtexture_t *dyntexture;
6417                 // check whether its a dynamic texture
6418                 // 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]
6419                 dyntexture = CL_GetDynTexture( basename );
6420                 item->base = dyntexture; // either NULL or dyntexture handle
6421         }
6422
6423         R_SkinFrame_MarkUsed(item);
6424         return item;
6425 }
6426
6427 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6428         { \
6429                 unsigned long long avgcolor[5], wsum; \
6430                 int pix, comp, w; \
6431                 avgcolor[0] = 0; \
6432                 avgcolor[1] = 0; \
6433                 avgcolor[2] = 0; \
6434                 avgcolor[3] = 0; \
6435                 avgcolor[4] = 0; \
6436                 wsum = 0; \
6437                 for(pix = 0; pix < cnt; ++pix) \
6438                 { \
6439                         w = 0; \
6440                         for(comp = 0; comp < 3; ++comp) \
6441                                 w += getpixel; \
6442                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6443                         { \
6444                                 ++wsum; \
6445                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6446                                 w = getpixel; \
6447                                 for(comp = 0; comp < 3; ++comp) \
6448                                         avgcolor[comp] += getpixel * w; \
6449                                 avgcolor[3] += w; \
6450                         } \
6451                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6452                         avgcolor[4] += getpixel; \
6453                 } \
6454                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6455                         avgcolor[3] = 1; \
6456                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6457                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6458                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6459                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6460         }
6461
6462 extern cvar_t gl_picmip;
6463 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6464 {
6465         int j;
6466         unsigned char *pixels;
6467         unsigned char *bumppixels;
6468         unsigned char *basepixels = NULL;
6469         int basepixels_width = 0;
6470         int basepixels_height = 0;
6471         skinframe_t *skinframe;
6472         rtexture_t *ddsbase = NULL;
6473         qboolean ddshasalpha = false;
6474         float ddsavgcolor[4];
6475         char basename[MAX_QPATH];
6476         int miplevel = R_PicmipForFlags(textureflags);
6477         int savemiplevel = miplevel;
6478         int mymiplevel;
6479
6480         if (cls.state == ca_dedicated)
6481                 return NULL;
6482
6483         // return an existing skinframe if already loaded
6484         // if loading of the first image fails, don't make a new skinframe as it
6485         // would cause all future lookups of this to be missing
6486         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6487         if (skinframe && skinframe->base)
6488                 return skinframe;
6489
6490         Image_StripImageExtension(name, basename, sizeof(basename));
6491
6492         // check for DDS texture file first
6493         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6494         {
6495                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6496                 if (basepixels == NULL)
6497                         return NULL;
6498         }
6499
6500         // FIXME handle miplevel
6501
6502         if (developer_loading.integer)
6503                 Con_Printf("loading skin \"%s\"\n", name);
6504
6505         // we've got some pixels to store, so really allocate this new texture now
6506         if (!skinframe)
6507                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6508         skinframe->stain = NULL;
6509         skinframe->merged = NULL;
6510         skinframe->base = NULL;
6511         skinframe->pants = NULL;
6512         skinframe->shirt = NULL;
6513         skinframe->nmap = NULL;
6514         skinframe->gloss = NULL;
6515         skinframe->glow = NULL;
6516         skinframe->fog = NULL;
6517         skinframe->reflect = NULL;
6518         skinframe->hasalpha = false;
6519
6520         if (ddsbase)
6521         {
6522                 skinframe->base = ddsbase;
6523                 skinframe->hasalpha = ddshasalpha;
6524                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6525                 if (r_loadfog && skinframe->hasalpha)
6526                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6527                 //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]);
6528         }
6529         else
6530         {
6531                 basepixels_width = image_width;
6532                 basepixels_height = image_height;
6533                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
6534                 if (textureflags & TEXF_ALPHA)
6535                 {
6536                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6537                         {
6538                                 if (basepixels[j] < 255)
6539                                 {
6540                                         skinframe->hasalpha = true;
6541                                         break;
6542                                 }
6543                         }
6544                         if (r_loadfog && skinframe->hasalpha)
6545                         {
6546                                 // has transparent pixels
6547                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6548                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6549                                 {
6550                                         pixels[j+0] = 255;
6551                                         pixels[j+1] = 255;
6552                                         pixels[j+2] = 255;
6553                                         pixels[j+3] = basepixels[j+3];
6554                                 }
6555                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
6556                                 Mem_Free(pixels);
6557                         }
6558                 }
6559                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6560                 //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]);
6561                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6562                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6563                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6564                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6565         }
6566
6567         if (r_loaddds)
6568         {
6569                 mymiplevel = savemiplevel;
6570                 if (r_loadnormalmap)
6571                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
6572                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6573                 if (r_loadgloss)
6574                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6575                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6576                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6577                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6578         }
6579
6580         // _norm is the name used by tenebrae and has been adopted as standard
6581         if (r_loadnormalmap && skinframe->nmap == NULL)
6582         {
6583                 mymiplevel = savemiplevel;
6584                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6585                 {
6586                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6587                         Mem_Free(pixels);
6588                         pixels = NULL;
6589                 }
6590                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6591                 {
6592                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6593                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6594                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6595                         Mem_Free(pixels);
6596                         Mem_Free(bumppixels);
6597                 }
6598                 else if (r_shadow_bumpscale_basetexture.value > 0)
6599                 {
6600                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6601                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6602                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6603                         Mem_Free(pixels);
6604                 }
6605                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6606                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6607         }
6608
6609         // _luma is supported only for tenebrae compatibility
6610         // _glow is the preferred name
6611         mymiplevel = savemiplevel;
6612         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel))))
6613         {
6614                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6615                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6616                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6617                 Mem_Free(pixels);pixels = NULL;
6618         }
6619
6620         mymiplevel = savemiplevel;
6621         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6622         {
6623                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6624                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6625                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6626                 Mem_Free(pixels);
6627                 pixels = NULL;
6628         }
6629
6630         mymiplevel = savemiplevel;
6631         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6632         {
6633                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6634                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6635                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6636                 Mem_Free(pixels);
6637                 pixels = NULL;
6638         }
6639
6640         mymiplevel = savemiplevel;
6641         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6642         {
6643                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6644                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6645                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6646                 Mem_Free(pixels);
6647                 pixels = NULL;
6648         }
6649
6650         mymiplevel = savemiplevel;
6651         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6652         {
6653                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6654                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6655                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6656                 Mem_Free(pixels);
6657                 pixels = NULL;
6658         }
6659
6660         if (basepixels)
6661                 Mem_Free(basepixels);
6662
6663         return skinframe;
6664 }
6665
6666 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6667 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6668 {
6669         int i;
6670         unsigned char *temp1, *temp2;
6671         skinframe_t *skinframe;
6672
6673         if (cls.state == ca_dedicated)
6674                 return NULL;
6675
6676         // if already loaded just return it, otherwise make a new skinframe
6677         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6678         if (skinframe && skinframe->base)
6679                 return skinframe;
6680
6681         skinframe->stain = NULL;
6682         skinframe->merged = NULL;
6683         skinframe->base = NULL;
6684         skinframe->pants = NULL;
6685         skinframe->shirt = NULL;
6686         skinframe->nmap = NULL;
6687         skinframe->gloss = NULL;
6688         skinframe->glow = NULL;
6689         skinframe->fog = NULL;
6690         skinframe->reflect = NULL;
6691         skinframe->hasalpha = false;
6692
6693         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6694         if (!skindata)
6695                 return NULL;
6696
6697         if (developer_loading.integer)
6698                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6699
6700         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6701         {
6702                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6703                 temp2 = temp1 + width * height * 4;
6704                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6705                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
6706                 Mem_Free(temp1);
6707         }
6708         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6709         if (textureflags & TEXF_ALPHA)
6710         {
6711                 for (i = 3;i < width * height * 4;i += 4)
6712                 {
6713                         if (skindata[i] < 255)
6714                         {
6715                                 skinframe->hasalpha = true;
6716                                 break;
6717                         }
6718                 }
6719                 if (r_loadfog && skinframe->hasalpha)
6720                 {
6721                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6722                         memcpy(fogpixels, skindata, width * height * 4);
6723                         for (i = 0;i < width * height * 4;i += 4)
6724                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6725                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6726                         Mem_Free(fogpixels);
6727                 }
6728         }
6729
6730         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6731         //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]);
6732
6733         return skinframe;
6734 }
6735
6736 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6737 {
6738         int i;
6739         int featuresmask;
6740         skinframe_t *skinframe;
6741
6742         if (cls.state == ca_dedicated)
6743                 return NULL;
6744
6745         // if already loaded just return it, otherwise make a new skinframe
6746         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6747         if (skinframe && skinframe->base)
6748                 return skinframe;
6749
6750         skinframe->stain = NULL;
6751         skinframe->merged = NULL;
6752         skinframe->base = NULL;
6753         skinframe->pants = NULL;
6754         skinframe->shirt = NULL;
6755         skinframe->nmap = NULL;
6756         skinframe->gloss = NULL;
6757         skinframe->glow = NULL;
6758         skinframe->fog = NULL;
6759         skinframe->reflect = NULL;
6760         skinframe->hasalpha = false;
6761
6762         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6763         if (!skindata)
6764                 return NULL;
6765
6766         if (developer_loading.integer)
6767                 Con_Printf("loading quake skin \"%s\"\n", name);
6768
6769         // 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)
6770         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6771         memcpy(skinframe->qpixels, skindata, width*height);
6772         skinframe->qwidth = width;
6773         skinframe->qheight = height;
6774
6775         featuresmask = 0;
6776         for (i = 0;i < width * height;i++)
6777                 featuresmask |= palette_featureflags[skindata[i]];
6778
6779         skinframe->hasalpha = false;
6780         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6781         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6782         skinframe->qgeneratemerged = true;
6783         skinframe->qgeneratebase = skinframe->qhascolormapping;
6784         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6785
6786         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6787         //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]);
6788
6789         return skinframe;
6790 }
6791
6792 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6793 {
6794         int width;
6795         int height;
6796         unsigned char *skindata;
6797
6798         if (!skinframe->qpixels)
6799                 return;
6800
6801         if (!skinframe->qhascolormapping)
6802                 colormapped = false;
6803
6804         if (colormapped)
6805         {
6806                 if (!skinframe->qgeneratebase)
6807                         return;
6808         }
6809         else
6810         {
6811                 if (!skinframe->qgeneratemerged)
6812                         return;
6813         }
6814
6815         width = skinframe->qwidth;
6816         height = skinframe->qheight;
6817         skindata = skinframe->qpixels;
6818
6819         if (skinframe->qgeneratenmap)
6820         {
6821                 unsigned char *temp1, *temp2;
6822                 skinframe->qgeneratenmap = false;
6823                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6824                 temp2 = temp1 + width * height * 4;
6825                 // use either a custom palette or the quake palette
6826                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6827                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6828                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
6829                 Mem_Free(temp1);
6830         }
6831
6832         if (skinframe->qgenerateglow)
6833         {
6834                 skinframe->qgenerateglow = false;
6835                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6836         }
6837
6838         if (colormapped)
6839         {
6840                 skinframe->qgeneratebase = false;
6841                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
6842                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6843                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6844         }
6845         else
6846         {
6847                 skinframe->qgeneratemerged = false;
6848                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
6849         }
6850
6851         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6852         {
6853                 Mem_Free(skinframe->qpixels);
6854                 skinframe->qpixels = NULL;
6855         }
6856 }
6857
6858 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)
6859 {
6860         int i;
6861         skinframe_t *skinframe;
6862
6863         if (cls.state == ca_dedicated)
6864                 return NULL;
6865
6866         // if already loaded just return it, otherwise make a new skinframe
6867         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6868         if (skinframe && skinframe->base)
6869                 return skinframe;
6870
6871         skinframe->stain = NULL;
6872         skinframe->merged = NULL;
6873         skinframe->base = NULL;
6874         skinframe->pants = NULL;
6875         skinframe->shirt = NULL;
6876         skinframe->nmap = NULL;
6877         skinframe->gloss = NULL;
6878         skinframe->glow = NULL;
6879         skinframe->fog = NULL;
6880         skinframe->reflect = NULL;
6881         skinframe->hasalpha = false;
6882
6883         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6884         if (!skindata)
6885                 return NULL;
6886
6887         if (developer_loading.integer)
6888                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6889
6890         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6891         if (textureflags & TEXF_ALPHA)
6892         {
6893                 for (i = 0;i < width * height;i++)
6894                 {
6895                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6896                         {
6897                                 skinframe->hasalpha = true;
6898                                 break;
6899                         }
6900                 }
6901                 if (r_loadfog && skinframe->hasalpha)
6902                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6903         }
6904
6905         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6906         //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]);
6907
6908         return skinframe;
6909 }
6910
6911 skinframe_t *R_SkinFrame_LoadMissing(void)
6912 {
6913         skinframe_t *skinframe;
6914
6915         if (cls.state == ca_dedicated)
6916                 return NULL;
6917
6918         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6919         skinframe->stain = NULL;
6920         skinframe->merged = NULL;
6921         skinframe->base = NULL;
6922         skinframe->pants = NULL;
6923         skinframe->shirt = NULL;
6924         skinframe->nmap = NULL;
6925         skinframe->gloss = NULL;
6926         skinframe->glow = NULL;
6927         skinframe->fog = NULL;
6928         skinframe->reflect = NULL;
6929         skinframe->hasalpha = false;
6930
6931         skinframe->avgcolor[0] = rand() / RAND_MAX;
6932         skinframe->avgcolor[1] = rand() / RAND_MAX;
6933         skinframe->avgcolor[2] = rand() / RAND_MAX;
6934         skinframe->avgcolor[3] = 1;
6935
6936         return skinframe;
6937 }
6938
6939 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6940 typedef struct suffixinfo_s
6941 {
6942         const char *suffix;
6943         qboolean flipx, flipy, flipdiagonal;
6944 }
6945 suffixinfo_t;
6946 static suffixinfo_t suffix[3][6] =
6947 {
6948         {
6949                 {"px",   false, false, false},
6950                 {"nx",   false, false, false},
6951                 {"py",   false, false, false},
6952                 {"ny",   false, false, false},
6953                 {"pz",   false, false, false},
6954                 {"nz",   false, false, false}
6955         },
6956         {
6957                 {"posx", false, false, false},
6958                 {"negx", false, false, false},
6959                 {"posy", false, false, false},
6960                 {"negy", false, false, false},
6961                 {"posz", false, false, false},
6962                 {"negz", false, false, false}
6963         },
6964         {
6965                 {"rt",    true, false,  true},
6966                 {"lf",   false,  true,  true},
6967                 {"ft",    true,  true, false},
6968                 {"bk",   false, false, false},
6969                 {"up",    true, false,  true},
6970                 {"dn",    true, false,  true}
6971         }
6972 };
6973
6974 static int componentorder[4] = {0, 1, 2, 3};
6975
6976 rtexture_t *R_LoadCubemap(const char *basename)
6977 {
6978         int i, j, cubemapsize;
6979         unsigned char *cubemappixels, *image_buffer;
6980         rtexture_t *cubemaptexture;
6981         char name[256];
6982         // must start 0 so the first loadimagepixels has no requested width/height
6983         cubemapsize = 0;
6984         cubemappixels = NULL;
6985         cubemaptexture = NULL;
6986         // keep trying different suffix groups (posx, px, rt) until one loads
6987         for (j = 0;j < 3 && !cubemappixels;j++)
6988         {
6989                 // load the 6 images in the suffix group
6990                 for (i = 0;i < 6;i++)
6991                 {
6992                         // generate an image name based on the base and and suffix
6993                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6994                         // load it
6995                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6996                         {
6997                                 // an image loaded, make sure width and height are equal
6998                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6999                                 {
7000                                         // if this is the first image to load successfully, allocate the cubemap memory
7001                                         if (!cubemappixels && image_width >= 1)
7002                                         {
7003                                                 cubemapsize = image_width;
7004                                                 // note this clears to black, so unavailable sides are black
7005                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7006                                         }
7007                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7008                                         if (cubemappixels)
7009                                                 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);
7010                                 }
7011                                 else
7012                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7013                                 // free the image
7014                                 Mem_Free(image_buffer);
7015                         }
7016                 }
7017         }
7018         // if a cubemap loaded, upload it
7019         if (cubemappixels)
7020         {
7021                 if (developer_loading.integer)
7022                         Con_Printf("loading cubemap \"%s\"\n", basename);
7023
7024                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7025                 Mem_Free(cubemappixels);
7026         }
7027         else
7028         {
7029                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7030                 if (developer_loading.integer)
7031                 {
7032                         Con_Printf("(tried tried images ");
7033                         for (j = 0;j < 3;j++)
7034                                 for (i = 0;i < 6;i++)
7035                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7036                         Con_Print(" and was unable to find any of them).\n");
7037                 }
7038         }
7039         return cubemaptexture;
7040 }
7041
7042 rtexture_t *R_GetCubemap(const char *basename)
7043 {
7044         int i;
7045         for (i = 0;i < r_texture_numcubemaps;i++)
7046                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7047                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7048         if (i >= MAX_CUBEMAPS)
7049                 return r_texture_whitecube;
7050         r_texture_numcubemaps++;
7051         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7052         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7053         return r_texture_cubemaps[i].texture;
7054 }
7055
7056 void R_FreeCubemaps(void)
7057 {
7058         int i;
7059         for (i = 0;i < r_texture_numcubemaps;i++)
7060         {
7061                 if (developer_loading.integer)
7062                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7063                 if (r_texture_cubemaps[i].texture)
7064                         R_FreeTexture(r_texture_cubemaps[i].texture);
7065         }
7066         r_texture_numcubemaps = 0;
7067 }
7068
7069 void R_Main_FreeViewCache(void)
7070 {
7071         if (r_refdef.viewcache.entityvisible)
7072                 Mem_Free(r_refdef.viewcache.entityvisible);
7073         if (r_refdef.viewcache.world_pvsbits)
7074                 Mem_Free(r_refdef.viewcache.world_pvsbits);
7075         if (r_refdef.viewcache.world_leafvisible)
7076                 Mem_Free(r_refdef.viewcache.world_leafvisible);
7077         if (r_refdef.viewcache.world_surfacevisible)
7078                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7079         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7080 }
7081
7082 void R_Main_ResizeViewCache(void)
7083 {
7084         int numentities = r_refdef.scene.numentities;
7085         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7086         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7087         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7088         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7089         if (r_refdef.viewcache.maxentities < numentities)
7090         {
7091                 r_refdef.viewcache.maxentities = numentities;
7092                 if (r_refdef.viewcache.entityvisible)
7093                         Mem_Free(r_refdef.viewcache.entityvisible);
7094                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7095         }
7096         if (r_refdef.viewcache.world_numclusters != numclusters)
7097         {
7098                 r_refdef.viewcache.world_numclusters = numclusters;
7099                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7100                 if (r_refdef.viewcache.world_pvsbits)
7101                         Mem_Free(r_refdef.viewcache.world_pvsbits);
7102                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7103         }
7104         if (r_refdef.viewcache.world_numleafs != numleafs)
7105         {
7106                 r_refdef.viewcache.world_numleafs = numleafs;
7107                 if (r_refdef.viewcache.world_leafvisible)
7108                         Mem_Free(r_refdef.viewcache.world_leafvisible);
7109                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7110         }
7111         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7112         {
7113                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7114                 if (r_refdef.viewcache.world_surfacevisible)
7115                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
7116                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7117         }
7118 }
7119
7120 extern rtexture_t *loadingscreentexture;
7121 void gl_main_start(void)
7122 {
7123         loadingscreentexture = NULL;
7124         r_texture_blanknormalmap = NULL;
7125         r_texture_white = NULL;
7126         r_texture_grey128 = NULL;
7127         r_texture_black = NULL;
7128         r_texture_whitecube = NULL;
7129         r_texture_normalizationcube = NULL;
7130         r_texture_fogattenuation = NULL;
7131         r_texture_fogheighttexture = NULL;
7132         r_texture_gammaramps = NULL;
7133         r_texture_numcubemaps = 0;
7134
7135         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
7136         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7137
7138         switch(vid.renderpath)
7139         {
7140         case RENDERPATH_GL20:
7141         case RENDERPATH_CGGL:
7142         case RENDERPATH_D3D9:
7143         case RENDERPATH_D3D10:
7144         case RENDERPATH_D3D11:
7145                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7146                 Cvar_SetValueQuick(&gl_combine, 1);
7147                 Cvar_SetValueQuick(&r_glsl, 1);
7148                 r_loadnormalmap = true;
7149                 r_loadgloss = true;
7150                 r_loadfog = false;
7151                 break;
7152         case RENDERPATH_GL13:
7153                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7154                 Cvar_SetValueQuick(&gl_combine, 1);
7155                 Cvar_SetValueQuick(&r_glsl, 0);
7156                 r_loadnormalmap = false;
7157                 r_loadgloss = false;
7158                 r_loadfog = true;
7159                 break;
7160         case RENDERPATH_GL11:
7161                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7162                 Cvar_SetValueQuick(&gl_combine, 0);
7163                 Cvar_SetValueQuick(&r_glsl, 0);
7164                 r_loadnormalmap = false;
7165                 r_loadgloss = false;
7166                 r_loadfog = true;
7167                 break;
7168         }
7169
7170         R_AnimCache_Free();
7171         R_FrameData_Reset();
7172
7173         r_numqueries = 0;
7174         r_maxqueries = 0;
7175         memset(r_queries, 0, sizeof(r_queries));
7176
7177         r_qwskincache = NULL;
7178         r_qwskincache_size = 0;
7179
7180         // set up r_skinframe loading system for textures
7181         memset(&r_skinframe, 0, sizeof(r_skinframe));
7182         r_skinframe.loadsequence = 1;
7183         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7184
7185         r_main_texturepool = R_AllocTexturePool();
7186         R_BuildBlankTextures();
7187         R_BuildNoTexture();
7188         if (vid.support.arb_texture_cube_map)
7189         {
7190                 R_BuildWhiteCube();
7191                 R_BuildNormalizationCube();
7192         }
7193         r_texture_fogattenuation = NULL;
7194         r_texture_fogheighttexture = NULL;
7195         r_texture_gammaramps = NULL;
7196         //r_texture_fogintensity = NULL;
7197         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7198         memset(&r_waterstate, 0, sizeof(r_waterstate));
7199         r_glsl_permutation = NULL;
7200         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7201         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7202         glslshaderstring = NULL;
7203 #ifdef SUPPORTCG
7204         r_cg_permutation = NULL;
7205         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7206         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7207         cgshaderstring = NULL;
7208 #endif
7209 #ifdef SUPPORTD3D
7210         r_hlsl_permutation = NULL;
7211         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7212         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7213         hlslshaderstring = NULL;
7214 #endif
7215         memset(&r_svbsp, 0, sizeof (r_svbsp));
7216
7217         r_refdef.fogmasktable_density = 0;
7218 }
7219
7220 void gl_main_shutdown(void)
7221 {
7222         R_AnimCache_Free();
7223         R_FrameData_Reset();
7224
7225         R_Main_FreeViewCache();
7226
7227         switch(vid.renderpath)
7228         {
7229         case RENDERPATH_GL11:
7230         case RENDERPATH_GL13:
7231         case RENDERPATH_GL20:
7232         case RENDERPATH_CGGL:
7233                 if (r_maxqueries)
7234                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7235                 break;
7236         case RENDERPATH_D3D9:
7237                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7238                 break;
7239         case RENDERPATH_D3D10:
7240                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7241                 break;
7242         case RENDERPATH_D3D11:
7243                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7244                 break;
7245         }
7246
7247         r_numqueries = 0;
7248         r_maxqueries = 0;
7249         memset(r_queries, 0, sizeof(r_queries));
7250
7251         r_qwskincache = NULL;
7252         r_qwskincache_size = 0;
7253
7254         // clear out the r_skinframe state
7255         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7256         memset(&r_skinframe, 0, sizeof(r_skinframe));
7257
7258         if (r_svbsp.nodes)
7259                 Mem_Free(r_svbsp.nodes);
7260         memset(&r_svbsp, 0, sizeof (r_svbsp));
7261         R_FreeTexturePool(&r_main_texturepool);
7262         loadingscreentexture = NULL;
7263         r_texture_blanknormalmap = NULL;
7264         r_texture_white = NULL;
7265         r_texture_grey128 = NULL;
7266         r_texture_black = NULL;
7267         r_texture_whitecube = NULL;
7268         r_texture_normalizationcube = NULL;
7269         r_texture_fogattenuation = NULL;
7270         r_texture_fogheighttexture = NULL;
7271         r_texture_gammaramps = NULL;
7272         r_texture_numcubemaps = 0;
7273         //r_texture_fogintensity = NULL;
7274         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7275         memset(&r_waterstate, 0, sizeof(r_waterstate));
7276         R_GLSL_Restart_f();
7277 }
7278
7279 extern void CL_ParseEntityLump(char *entitystring);
7280 void gl_main_newmap(void)
7281 {
7282         // FIXME: move this code to client
7283         char *entities, entname[MAX_QPATH];
7284         if (r_qwskincache)
7285                 Mem_Free(r_qwskincache);
7286         r_qwskincache = NULL;
7287         r_qwskincache_size = 0;
7288         if (cl.worldmodel)
7289         {
7290                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7291                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7292                 {
7293                         CL_ParseEntityLump(entities);
7294                         Mem_Free(entities);
7295                         return;
7296                 }
7297                 if (cl.worldmodel->brush.entities)
7298                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7299         }
7300         R_Main_FreeViewCache();
7301
7302         R_FrameData_Reset();
7303 }
7304
7305 void GL_Main_Init(void)
7306 {
7307         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7308
7309         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7310         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7311         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7312         if (gamemode == GAME_NEHAHRA)
7313         {
7314                 Cvar_RegisterVariable (&gl_fogenable);
7315                 Cvar_RegisterVariable (&gl_fogdensity);
7316                 Cvar_RegisterVariable (&gl_fogred);
7317                 Cvar_RegisterVariable (&gl_foggreen);
7318                 Cvar_RegisterVariable (&gl_fogblue);
7319                 Cvar_RegisterVariable (&gl_fogstart);
7320                 Cvar_RegisterVariable (&gl_fogend);
7321                 Cvar_RegisterVariable (&gl_skyclip);
7322         }
7323         Cvar_RegisterVariable(&r_motionblur);
7324         Cvar_RegisterVariable(&r_motionblur_maxblur);
7325         Cvar_RegisterVariable(&r_motionblur_bmin);
7326         Cvar_RegisterVariable(&r_motionblur_vmin);
7327         Cvar_RegisterVariable(&r_motionblur_vmax);
7328         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7329         Cvar_RegisterVariable(&r_motionblur_randomize);
7330         Cvar_RegisterVariable(&r_damageblur);
7331         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7332         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7333         Cvar_RegisterVariable(&r_equalize_entities_by);
7334         Cvar_RegisterVariable(&r_equalize_entities_to);
7335         Cvar_RegisterVariable(&r_depthfirst);
7336         Cvar_RegisterVariable(&r_useinfinitefarclip);
7337         Cvar_RegisterVariable(&r_farclip_base);
7338         Cvar_RegisterVariable(&r_farclip_world);
7339         Cvar_RegisterVariable(&r_nearclip);
7340         Cvar_RegisterVariable(&r_showbboxes);
7341         Cvar_RegisterVariable(&r_showsurfaces);
7342         Cvar_RegisterVariable(&r_showtris);
7343         Cvar_RegisterVariable(&r_shownormals);
7344         Cvar_RegisterVariable(&r_showlighting);
7345         Cvar_RegisterVariable(&r_showshadowvolumes);
7346         Cvar_RegisterVariable(&r_showcollisionbrushes);
7347         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7348         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7349         Cvar_RegisterVariable(&r_showdisabledepthtest);
7350         Cvar_RegisterVariable(&r_drawportals);
7351         Cvar_RegisterVariable(&r_drawentities);
7352         Cvar_RegisterVariable(&r_draw2d);
7353         Cvar_RegisterVariable(&r_drawworld);
7354         Cvar_RegisterVariable(&r_cullentities_trace);
7355         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7356         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7357         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7358         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7359         Cvar_RegisterVariable(&r_drawviewmodel);
7360         Cvar_RegisterVariable(&r_drawexteriormodel);
7361         Cvar_RegisterVariable(&r_speeds);
7362         Cvar_RegisterVariable(&r_fullbrights);
7363         Cvar_RegisterVariable(&r_wateralpha);
7364         Cvar_RegisterVariable(&r_dynamic);
7365         Cvar_RegisterVariable(&r_fakelight);
7366         Cvar_RegisterVariable(&r_fakelight_intensity);
7367         Cvar_RegisterVariable(&r_fullbright);
7368         Cvar_RegisterVariable(&r_shadows);
7369         Cvar_RegisterVariable(&r_shadows_darken);
7370         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7371         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7372         Cvar_RegisterVariable(&r_shadows_throwdistance);
7373         Cvar_RegisterVariable(&r_shadows_throwdirection);
7374         Cvar_RegisterVariable(&r_shadows_focus);
7375         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7376         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7377         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7378         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7379         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7380         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7381         Cvar_RegisterVariable(&r_fog_exp2);
7382         Cvar_RegisterVariable(&r_drawfog);
7383         Cvar_RegisterVariable(&r_transparentdepthmasking);
7384         Cvar_RegisterVariable(&r_texture_dds_load);
7385         Cvar_RegisterVariable(&r_texture_dds_save);
7386         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7387         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7388         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7389         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7390         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7391         Cvar_RegisterVariable(&r_textureunits);
7392         Cvar_RegisterVariable(&gl_combine);
7393         Cvar_RegisterVariable(&r_glsl);
7394         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7395         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7396         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7397         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7398         Cvar_RegisterVariable(&r_glsl_postprocess);
7399         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7400         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7401         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7402         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7403         Cvar_RegisterVariable(&r_water);
7404         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7405         Cvar_RegisterVariable(&r_water_clippingplanebias);
7406         Cvar_RegisterVariable(&r_water_refractdistort);
7407         Cvar_RegisterVariable(&r_water_reflectdistort);
7408         Cvar_RegisterVariable(&r_water_scissormode);
7409         Cvar_RegisterVariable(&r_lerpsprites);
7410         Cvar_RegisterVariable(&r_lerpmodels);
7411         Cvar_RegisterVariable(&r_lerplightstyles);
7412         Cvar_RegisterVariable(&r_waterscroll);
7413         Cvar_RegisterVariable(&r_bloom);
7414         Cvar_RegisterVariable(&r_bloom_colorscale);
7415         Cvar_RegisterVariable(&r_bloom_brighten);
7416         Cvar_RegisterVariable(&r_bloom_blur);
7417         Cvar_RegisterVariable(&r_bloom_resolution);
7418         Cvar_RegisterVariable(&r_bloom_colorexponent);
7419         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7420         Cvar_RegisterVariable(&r_hdr);
7421         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7422         Cvar_RegisterVariable(&r_hdr_glowintensity);
7423         Cvar_RegisterVariable(&r_hdr_range);
7424         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7425         Cvar_RegisterVariable(&developer_texturelogging);
7426         Cvar_RegisterVariable(&gl_lightmaps);
7427         Cvar_RegisterVariable(&r_test);
7428         Cvar_RegisterVariable(&r_glsl_saturation);
7429         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7430         Cvar_RegisterVariable(&r_framedatasize);
7431         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7432                 Cvar_SetValue("r_fullbrights", 0);
7433         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7434
7435         Cvar_RegisterVariable(&r_track_sprites);
7436         Cvar_RegisterVariable(&r_track_sprites_flags);
7437         Cvar_RegisterVariable(&r_track_sprites_scalew);
7438         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7439         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7440         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7441 }
7442
7443 extern void R_Textures_Init(void);
7444 extern void GL_Draw_Init(void);
7445 extern void GL_Main_Init(void);
7446 extern void R_Shadow_Init(void);
7447 extern void R_Sky_Init(void);
7448 extern void GL_Surf_Init(void);
7449 extern void R_Particles_Init(void);
7450 extern void R_Explosion_Init(void);
7451 extern void gl_backend_init(void);
7452 extern void Sbar_Init(void);
7453 extern void R_LightningBeams_Init(void);
7454 extern void Mod_RenderInit(void);
7455 extern void Font_Init(void);
7456
7457 void Render_Init(void)
7458 {
7459         gl_backend_init();
7460         R_Textures_Init();
7461         GL_Main_Init();
7462         Font_Init();
7463         GL_Draw_Init();
7464         R_Shadow_Init();
7465         R_Sky_Init();
7466         GL_Surf_Init();
7467         Sbar_Init();
7468         R_Particles_Init();
7469         R_Explosion_Init();
7470         R_LightningBeams_Init();
7471         Mod_RenderInit();
7472 }
7473
7474 /*
7475 ===============
7476 GL_Init
7477 ===============
7478 */
7479 extern char *ENGINE_EXTENSIONS;
7480 void GL_Init (void)
7481 {
7482         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7483         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7484         gl_version = (const char *)qglGetString(GL_VERSION);
7485         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7486
7487         if (!gl_extensions)
7488                 gl_extensions = "";
7489         if (!gl_platformextensions)
7490                 gl_platformextensions = "";
7491
7492         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7493         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7494         Con_Printf("GL_VERSION: %s\n", gl_version);
7495         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7496         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7497
7498         VID_CheckExtensions();
7499
7500         // LordHavoc: report supported extensions
7501         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7502
7503         // clear to black (loading plaque will be seen over this)
7504         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7505 }
7506
7507 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7508 {
7509         int i;
7510         mplane_t *p;
7511         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7512         {
7513                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7514                 if (i == 4)
7515                         continue;
7516                 p = r_refdef.view.frustum + i;
7517                 switch(p->signbits)
7518                 {
7519                 default:
7520                 case 0:
7521                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7522                                 return true;
7523                         break;
7524                 case 1:
7525                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7526                                 return true;
7527                         break;
7528                 case 2:
7529                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7530                                 return true;
7531                         break;
7532                 case 3:
7533                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7534                                 return true;
7535                         break;
7536                 case 4:
7537                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7538                                 return true;
7539                         break;
7540                 case 5:
7541                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7542                                 return true;
7543                         break;
7544                 case 6:
7545                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7546                                 return true;
7547                         break;
7548                 case 7:
7549                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7550                                 return true;
7551                         break;
7552                 }
7553         }
7554         return false;
7555 }
7556
7557 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7558 {
7559         int i;
7560         const mplane_t *p;
7561         for (i = 0;i < numplanes;i++)
7562         {
7563                 p = planes + i;
7564                 switch(p->signbits)
7565                 {
7566                 default:
7567                 case 0:
7568                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7569                                 return true;
7570                         break;
7571                 case 1:
7572                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7573                                 return true;
7574                         break;
7575                 case 2:
7576                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7577                                 return true;
7578                         break;
7579                 case 3:
7580                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7581                                 return true;
7582                         break;
7583                 case 4:
7584                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7585                                 return true;
7586                         break;
7587                 case 5:
7588                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7589                                 return true;
7590                         break;
7591                 case 6:
7592                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7593                                 return true;
7594                         break;
7595                 case 7:
7596                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7597                                 return true;
7598                         break;
7599                 }
7600         }
7601         return false;
7602 }
7603
7604 //==================================================================================
7605
7606 // LordHavoc: this stores temporary data used within the same frame
7607
7608 qboolean r_framedata_failed;
7609 static size_t r_framedata_size;
7610 static size_t r_framedata_current;
7611 static void *r_framedata_base;
7612
7613 void R_FrameData_Reset(void)
7614 {
7615         if (r_framedata_base)
7616                 Mem_Free(r_framedata_base);
7617         r_framedata_base = NULL;
7618         r_framedata_size = 0;
7619         r_framedata_current = 0;
7620         r_framedata_failed = false;
7621 }
7622
7623 void R_FrameData_NewFrame(void)
7624 {
7625         size_t wantedsize;
7626         if (r_framedata_failed)
7627                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7628         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7629         wantedsize = bound(65536, wantedsize, 128*1024*1024);
7630         if (r_framedata_size != wantedsize)
7631         {
7632                 r_framedata_size = wantedsize;
7633                 if (r_framedata_base)
7634                         Mem_Free(r_framedata_base);
7635                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7636         }
7637         r_framedata_current = 0;
7638         r_framedata_failed = false;
7639 }
7640
7641 void *R_FrameData_Alloc(size_t size)
7642 {
7643         void *data;
7644
7645         // align to 16 byte boundary
7646         size = (size + 15) & ~15;
7647         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7648         r_framedata_current += size;
7649
7650         // check overflow
7651         if (r_framedata_current > r_framedata_size)
7652                 r_framedata_failed = true;
7653
7654         // return NULL on everything after a failure
7655         if (r_framedata_failed)
7656                 return NULL;
7657
7658         return data;
7659 }
7660
7661 void *R_FrameData_Store(size_t size, void *data)
7662 {
7663         void *d = R_FrameData_Alloc(size);
7664         if (d)
7665                 memcpy(d, data, size);
7666         return d;
7667 }
7668
7669 //==================================================================================
7670
7671 // LordHavoc: animcache originally written by Echon, rewritten since then
7672
7673 /**
7674  * Animation cache prevents re-generating mesh data for an animated model
7675  * multiple times in one frame for lighting, shadowing, reflections, etc.
7676  */
7677
7678 void R_AnimCache_Free(void)
7679 {
7680 }
7681
7682 void R_AnimCache_ClearCache(void)
7683 {
7684         int i;
7685         entity_render_t *ent;
7686
7687         for (i = 0;i < r_refdef.scene.numentities;i++)
7688         {
7689                 ent = r_refdef.scene.entities[i];
7690                 ent->animcache_vertex3f = NULL;
7691                 ent->animcache_normal3f = NULL;
7692                 ent->animcache_svector3f = NULL;
7693                 ent->animcache_tvector3f = NULL;
7694                 ent->animcache_vertexposition = NULL;
7695                 ent->animcache_vertexmesh = NULL;
7696                 ent->animcache_vertexpositionbuffer = NULL;
7697                 ent->animcache_vertexmeshbuffer = NULL;
7698         }
7699 }
7700
7701 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7702 {
7703         int i;
7704
7705         // identical memory layout, so no need to allocate...
7706         // this also provides the vertexposition structure to everything, e.g.
7707         // depth masked rendering currently uses it even if having separate
7708         // arrays
7709         // NOTE: get rid of this optimization if changing it to e.g. 4f
7710         ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7711
7712         // TODO:
7713         // get rid of following uses of VERTEXPOSITION, change to the array:
7714         // R_DrawTextureSurfaceList_Sky if skyrendermasked
7715         // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7716         // R_DrawTextureSurfaceList_DepthOnly
7717         // R_Q1BSP_DrawShadowMap
7718
7719         switch(vid.renderpath)
7720         {
7721         case RENDERPATH_GL20:
7722         case RENDERPATH_CGGL:
7723                 // need the meshbuffers if !gl_mesh_separatearrays.integer
7724                 if (gl_mesh_separatearrays.integer)
7725                         return;
7726                 break;
7727         case RENDERPATH_D3D9:
7728         case RENDERPATH_D3D10:
7729         case RENDERPATH_D3D11:
7730                 // always need the meshbuffers
7731                 break;
7732         case RENDERPATH_GL13:
7733         case RENDERPATH_GL11:
7734                 // never need the meshbuffers
7735                 return;
7736         }
7737
7738         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7739                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7740         /*
7741         if (!ent->animcache_vertexposition)
7742                 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7743         */
7744         if (ent->animcache_vertexposition)
7745         {
7746                 /*
7747                 for (i = 0;i < numvertices;i++)
7748                         memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7749                 */
7750                 // TODO: upload vertex buffer?
7751         }
7752         if (ent->animcache_vertexmesh)
7753         {
7754                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7755                 for (i = 0;i < numvertices;i++)
7756                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7757                 if (ent->animcache_svector3f)
7758                         for (i = 0;i < numvertices;i++)
7759                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7760                 if (ent->animcache_tvector3f)
7761                         for (i = 0;i < numvertices;i++)
7762                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7763                 if (ent->animcache_normal3f)
7764                         for (i = 0;i < numvertices;i++)
7765                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7766                 // TODO: upload vertex buffer?
7767         }
7768 }
7769
7770 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7771 {
7772         dp_model_t *model = ent->model;
7773         int numvertices;
7774         // see if it's already cached this frame
7775         if (ent->animcache_vertex3f)
7776         {
7777                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7778                 if (wantnormals || wanttangents)
7779                 {
7780                         if (ent->animcache_normal3f)
7781                                 wantnormals = false;
7782                         if (ent->animcache_svector3f)
7783                                 wanttangents = false;
7784                         if (wantnormals || wanttangents)
7785                         {
7786                                 numvertices = model->surfmesh.num_vertices;
7787                                 if (wantnormals)
7788                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7789                                 if (wanttangents)
7790                                 {
7791                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7792                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7793                                 }
7794                                 if (!r_framedata_failed)
7795                                 {
7796                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7797                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7798                                 }
7799                         }
7800                 }
7801         }
7802         else
7803         {
7804                 // see if this ent is worth caching
7805                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7806                         return false;
7807                 // get some memory for this entity and generate mesh data
7808                 numvertices = model->surfmesh.num_vertices;
7809                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7810                 if (wantnormals)
7811                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7812                 if (wanttangents)
7813                 {
7814                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7815                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7816                 }
7817                 if (!r_framedata_failed)
7818                 {
7819                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7820                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7821                 }
7822         }
7823         return !r_framedata_failed;
7824 }
7825
7826 void R_AnimCache_CacheVisibleEntities(void)
7827 {
7828         int i;
7829         qboolean wantnormals = true;
7830         qboolean wanttangents = !r_showsurfaces.integer;
7831
7832         switch(vid.renderpath)
7833         {
7834         case RENDERPATH_GL20:
7835         case RENDERPATH_CGGL:
7836         case RENDERPATH_D3D9:
7837         case RENDERPATH_D3D10:
7838         case RENDERPATH_D3D11:
7839                 break;
7840         case RENDERPATH_GL13:
7841         case RENDERPATH_GL11:
7842                 wanttangents = false;
7843                 break;
7844         }
7845
7846         if (r_shownormals.integer)
7847                 wanttangents = wantnormals = true;
7848
7849         // TODO: thread this
7850         // NOTE: R_PrepareRTLights() also caches entities
7851
7852         for (i = 0;i < r_refdef.scene.numentities;i++)
7853                 if (r_refdef.viewcache.entityvisible[i])
7854                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7855 }
7856
7857 //==================================================================================
7858
7859 static void R_View_UpdateEntityLighting (void)
7860 {
7861         int i;
7862         entity_render_t *ent;
7863         vec3_t tempdiffusenormal, avg;
7864         vec_t f, fa, fd, fdd;
7865         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7866
7867         for (i = 0;i < r_refdef.scene.numentities;i++)
7868         {
7869                 ent = r_refdef.scene.entities[i];
7870
7871                 // skip unseen models
7872                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7873                         continue;
7874
7875                 // skip bsp models
7876                 if (ent->model && ent->model->brush.num_leafs)
7877                 {
7878                         // TODO: use modellight for r_ambient settings on world?
7879                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7880                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7881                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7882                         continue;
7883                 }
7884
7885                 // fetch the lighting from the worldmodel data
7886                 VectorClear(ent->modellight_ambient);
7887                 VectorClear(ent->modellight_diffuse);
7888                 VectorClear(tempdiffusenormal);
7889                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7890                 {
7891                         vec3_t org;
7892                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7893                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7894                         if(ent->flags & RENDER_EQUALIZE)
7895                         {
7896                                 // first fix up ambient lighting...
7897                                 if(r_equalize_entities_minambient.value > 0)
7898                                 {
7899                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7900                                         if(fd > 0)
7901                                         {
7902                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7903                                                 if(fa < r_equalize_entities_minambient.value * fd)
7904                                                 {
7905                                                         // solve:
7906                                                         //   fa'/fd' = minambient
7907                                                         //   fa'+0.25*fd' = fa+0.25*fd
7908                                                         //   ...
7909                                                         //   fa' = fd' * minambient
7910                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7911                                                         //   ...
7912                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7913                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7914                                                         //   ...
7915                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7916                                                         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
7917                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7918                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7919                                                 }
7920                                         }
7921                                 }
7922
7923                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7924                                 {
7925                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7926                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7927                                         if(f > 0)
7928                                         {
7929                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7930                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7931                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7932                                         }
7933                                 }
7934                         }
7935                 }
7936                 else // highly rare
7937                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7938
7939                 // move the light direction into modelspace coordinates for lighting code
7940                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7941                 if(VectorLength2(ent->modellight_lightdir) == 0)
7942                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7943                 VectorNormalize(ent->modellight_lightdir);
7944         }
7945 }
7946
7947 #define MAX_LINEOFSIGHTTRACES 64
7948
7949 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7950 {
7951         int i;
7952         vec3_t boxmins, boxmaxs;
7953         vec3_t start;
7954         vec3_t end;
7955         dp_model_t *model = r_refdef.scene.worldmodel;
7956
7957         if (!model || !model->brush.TraceLineOfSight)
7958                 return true;
7959
7960         // expand the box a little
7961         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7962         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7963         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7964         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7965         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7966         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7967
7968         // return true if eye is inside enlarged box
7969         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7970                 return true;
7971
7972         // try center
7973         VectorCopy(eye, start);
7974         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7975         if (model->brush.TraceLineOfSight(model, start, end))
7976                 return true;
7977
7978         // try various random positions
7979         for (i = 0;i < numsamples;i++)
7980         {
7981                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7982                 if (model->brush.TraceLineOfSight(model, start, end))
7983                         return true;
7984         }
7985
7986         return false;
7987 }
7988
7989
7990 static void R_View_UpdateEntityVisible (void)
7991 {
7992         int i;
7993         int renderimask;
7994         int samples;
7995         entity_render_t *ent;
7996
7997         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7998                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7999                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
8000                 :                                                          RENDER_EXTERIORMODEL;
8001         if (!r_drawviewmodel.integer)
8002                 renderimask |= RENDER_VIEWMODEL;
8003         if (!r_drawexteriormodel.integer)
8004                 renderimask |= RENDER_EXTERIORMODEL;
8005         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8006         {
8007                 // worldmodel can check visibility
8008                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8009                 for (i = 0;i < r_refdef.scene.numentities;i++)
8010                 {
8011                         ent = r_refdef.scene.entities[i];
8012                         if (!(ent->flags & renderimask))
8013                         if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
8014                         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))
8015                                 r_refdef.viewcache.entityvisible[i] = true;
8016                 }
8017                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8018                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8019                 {
8020                         for (i = 0;i < r_refdef.scene.numentities;i++)
8021                         {
8022                                 ent = r_refdef.scene.entities[i];
8023                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8024                                 {
8025                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8026                                         if (samples < 0)
8027                                                 continue; // temp entities do pvs only
8028                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8029                                                 ent->last_trace_visibility = realtime;
8030                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8031                                                 r_refdef.viewcache.entityvisible[i] = 0;
8032                                 }
8033                         }
8034                 }
8035         }
8036         else
8037         {
8038                 // no worldmodel or it can't check visibility
8039                 for (i = 0;i < r_refdef.scene.numentities;i++)
8040                 {
8041                         ent = r_refdef.scene.entities[i];
8042                         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));
8043                 }
8044         }
8045 }
8046
8047 /// only used if skyrendermasked, and normally returns false
8048 int R_DrawBrushModelsSky (void)
8049 {
8050         int i, sky;
8051         entity_render_t *ent;
8052
8053         sky = false;
8054         for (i = 0;i < r_refdef.scene.numentities;i++)
8055         {
8056                 if (!r_refdef.viewcache.entityvisible[i])
8057                         continue;
8058                 ent = r_refdef.scene.entities[i];
8059                 if (!ent->model || !ent->model->DrawSky)
8060                         continue;
8061                 ent->model->DrawSky(ent);
8062                 sky = true;
8063         }
8064         return sky;
8065 }
8066
8067 static void R_DrawNoModel(entity_render_t *ent);
8068 static void R_DrawModels(void)
8069 {
8070         int i;
8071         entity_render_t *ent;
8072
8073         for (i = 0;i < r_refdef.scene.numentities;i++)
8074         {
8075                 if (!r_refdef.viewcache.entityvisible[i])
8076                         continue;
8077                 ent = r_refdef.scene.entities[i];
8078                 r_refdef.stats.entities++;
8079                 if (ent->model && ent->model->Draw != NULL)
8080                         ent->model->Draw(ent);
8081                 else
8082                         R_DrawNoModel(ent);
8083         }
8084 }
8085
8086 static void R_DrawModelsDepth(void)
8087 {
8088         int i;
8089         entity_render_t *ent;
8090
8091         for (i = 0;i < r_refdef.scene.numentities;i++)
8092         {
8093                 if (!r_refdef.viewcache.entityvisible[i])
8094                         continue;
8095                 ent = r_refdef.scene.entities[i];
8096                 if (ent->model && ent->model->DrawDepth != NULL)
8097                         ent->model->DrawDepth(ent);
8098         }
8099 }
8100
8101 static void R_DrawModelsDebug(void)
8102 {
8103         int i;
8104         entity_render_t *ent;
8105
8106         for (i = 0;i < r_refdef.scene.numentities;i++)
8107         {
8108                 if (!r_refdef.viewcache.entityvisible[i])
8109                         continue;
8110                 ent = r_refdef.scene.entities[i];
8111                 if (ent->model && ent->model->DrawDebug != NULL)
8112                         ent->model->DrawDebug(ent);
8113         }
8114 }
8115
8116 static void R_DrawModelsAddWaterPlanes(void)
8117 {
8118         int i;
8119         entity_render_t *ent;
8120
8121         for (i = 0;i < r_refdef.scene.numentities;i++)
8122         {
8123                 if (!r_refdef.viewcache.entityvisible[i])
8124                         continue;
8125                 ent = r_refdef.scene.entities[i];
8126                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8127                         ent->model->DrawAddWaterPlanes(ent);
8128         }
8129 }
8130
8131 static void R_View_SetFrustum(const int *scissor)
8132 {
8133         int i;
8134         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8135         vec3_t forward, left, up, origin, v;
8136
8137         if(scissor)
8138         {
8139                 // flipped x coordinates (because x points left here)
8140                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8141                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8142
8143                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8144                 switch(vid.renderpath)
8145                 {
8146                         case RENDERPATH_D3D9:
8147                         case RENDERPATH_D3D10:
8148                         case RENDERPATH_D3D11:
8149                                 // non-flipped y coordinates
8150                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8151                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8152                                 break;
8153                         case RENDERPATH_GL11:
8154                         case RENDERPATH_GL13:
8155                         case RENDERPATH_GL20:
8156                         case RENDERPATH_CGGL:
8157                                 // non-flipped y coordinates
8158                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8159                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8160                                 break;
8161                 }
8162         }
8163
8164         // we can't trust r_refdef.view.forward and friends in reflected scenes
8165         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8166
8167 #if 0
8168         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8169         r_refdef.view.frustum[0].normal[1] = 0 - 0;
8170         r_refdef.view.frustum[0].normal[2] = -1 - 0;
8171         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8172         r_refdef.view.frustum[1].normal[1] = 0 + 0;
8173         r_refdef.view.frustum[1].normal[2] = -1 + 0;
8174         r_refdef.view.frustum[2].normal[0] = 0 - 0;
8175         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8176         r_refdef.view.frustum[2].normal[2] = -1 - 0;
8177         r_refdef.view.frustum[3].normal[0] = 0 + 0;
8178         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8179         r_refdef.view.frustum[3].normal[2] = -1 + 0;
8180 #endif
8181
8182 #if 0
8183         zNear = r_refdef.nearclip;
8184         nudge = 1.0 - 1.0 / (1<<23);
8185         r_refdef.view.frustum[4].normal[0] = 0 - 0;
8186         r_refdef.view.frustum[4].normal[1] = 0 - 0;
8187         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8188         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8189         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8190         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8191         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8192         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8193 #endif
8194
8195
8196
8197 #if 0
8198         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8199         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8200         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8201         r_refdef.view.frustum[0].dist = m[15] - m[12];
8202
8203         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8204         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8205         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8206         r_refdef.view.frustum[1].dist = m[15] + m[12];
8207
8208         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8209         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8210         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8211         r_refdef.view.frustum[2].dist = m[15] - m[13];
8212
8213         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8214         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8215         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8216         r_refdef.view.frustum[3].dist = m[15] + m[13];
8217
8218         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8219         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8220         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8221         r_refdef.view.frustum[4].dist = m[15] - m[14];
8222
8223         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8224         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8225         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8226         r_refdef.view.frustum[5].dist = m[15] + m[14];
8227 #endif
8228
8229         if (r_refdef.view.useperspective)
8230         {
8231                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8232                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
8233                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
8234                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
8235                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
8236
8237                 // then the normals from the corners relative to origin
8238                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8239                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8240                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8241                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8242
8243                 // in a NORMAL view, forward cross left == up
8244                 // in a REFLECTED view, forward cross left == down
8245                 // so our cross products above need to be adjusted for a left handed coordinate system
8246                 CrossProduct(forward, left, v);
8247                 if(DotProduct(v, up) < 0)
8248                 {
8249                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8250                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8251                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8252                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8253                 }
8254
8255                 // Leaving those out was a mistake, those were in the old code, and they
8256                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8257                 // I couldn't reproduce it after adding those normalizations. --blub
8258                 VectorNormalize(r_refdef.view.frustum[0].normal);
8259                 VectorNormalize(r_refdef.view.frustum[1].normal);
8260                 VectorNormalize(r_refdef.view.frustum[2].normal);
8261                 VectorNormalize(r_refdef.view.frustum[3].normal);
8262
8263                 // make the corners absolute
8264                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8265                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8266                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8267                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8268
8269                 // one more normal
8270                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8271
8272                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8273                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8274                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8275                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8276                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8277         }
8278         else
8279         {
8280                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8281                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8282                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8283                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8284                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8285                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8286                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8287                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8288                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8289                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8290         }
8291         r_refdef.view.numfrustumplanes = 5;
8292
8293         if (r_refdef.view.useclipplane)
8294         {
8295                 r_refdef.view.numfrustumplanes = 6;
8296                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8297         }
8298
8299         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8300                 PlaneClassify(r_refdef.view.frustum + i);
8301
8302         // LordHavoc: note to all quake engine coders, Quake had a special case
8303         // for 90 degrees which assumed a square view (wrong), so I removed it,
8304         // Quake2 has it disabled as well.
8305
8306         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8307         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8308         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8309         //PlaneClassify(&frustum[0]);
8310
8311         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8312         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8313         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8314         //PlaneClassify(&frustum[1]);
8315
8316         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8317         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8318         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8319         //PlaneClassify(&frustum[2]);
8320
8321         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8322         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8323         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8324         //PlaneClassify(&frustum[3]);
8325
8326         // nearclip plane
8327         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8328         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8329         //PlaneClassify(&frustum[4]);
8330 }
8331
8332 void R_View_UpdateWithScissor(const int *myscissor)
8333 {
8334         R_Main_ResizeViewCache();
8335         R_View_SetFrustum(myscissor);
8336         R_View_WorldVisibility(r_refdef.view.useclipplane);
8337         R_View_UpdateEntityVisible();
8338         R_View_UpdateEntityLighting();
8339 }
8340
8341 void R_View_Update(void)
8342 {
8343         R_Main_ResizeViewCache();
8344         R_View_SetFrustum(NULL);
8345         R_View_WorldVisibility(r_refdef.view.useclipplane);
8346         R_View_UpdateEntityVisible();
8347         R_View_UpdateEntityLighting();
8348 }
8349
8350 void R_SetupView(qboolean allowwaterclippingplane)
8351 {
8352         const float *customclipplane = NULL;
8353         float plane[4];
8354         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8355         {
8356                 // LordHavoc: couldn't figure out how to make this approach the
8357                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8358                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8359                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8360                         dist = r_refdef.view.clipplane.dist;
8361                 plane[0] = r_refdef.view.clipplane.normal[0];
8362                 plane[1] = r_refdef.view.clipplane.normal[1];
8363                 plane[2] = r_refdef.view.clipplane.normal[2];
8364                 plane[3] = dist;
8365                 customclipplane = plane;
8366         }
8367
8368         if (!r_refdef.view.useperspective)
8369                 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);
8370         else if (vid.stencil && r_useinfinitefarclip.integer)
8371                 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);
8372         else
8373                 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);
8374         R_SetViewport(&r_refdef.view.viewport);
8375 }
8376
8377 void R_EntityMatrix(const matrix4x4_t *matrix)
8378 {
8379         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8380         {
8381                 gl_modelmatrixchanged = false;
8382                 gl_modelmatrix = *matrix;
8383                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8384                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8385                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8386                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8387                 CHECKGLERROR
8388                 switch(vid.renderpath)
8389                 {
8390                 case RENDERPATH_D3D9:
8391 #ifdef SUPPORTD3D
8392                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8393                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8394 #endif
8395                         break;
8396                 case RENDERPATH_D3D10:
8397                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8398                         break;
8399                 case RENDERPATH_D3D11:
8400                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8401                         break;
8402                 case RENDERPATH_GL20:
8403                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8404                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8405                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8406                         break;
8407                 case RENDERPATH_CGGL:
8408 #ifdef SUPPORTCG
8409                         CHECKCGERROR
8410                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8411                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8412                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8413 #endif
8414                         break;
8415                 case RENDERPATH_GL13:
8416                 case RENDERPATH_GL11:
8417                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8418                         break;
8419                 }
8420         }
8421 }
8422
8423 void R_ResetViewRendering2D(void)
8424 {
8425         r_viewport_t viewport;
8426         DrawQ_Finish();
8427
8428         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8429         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);
8430         R_SetViewport(&viewport);
8431         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8432         GL_Color(1, 1, 1, 1);
8433         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8434         GL_BlendFunc(GL_ONE, GL_ZERO);
8435         GL_AlphaTest(false);
8436         GL_ScissorTest(false);
8437         GL_DepthMask(false);
8438         GL_DepthRange(0, 1);
8439         GL_DepthTest(false);
8440         GL_DepthFunc(GL_LEQUAL);
8441         R_EntityMatrix(&identitymatrix);
8442         R_Mesh_ResetTextureState();
8443         GL_PolygonOffset(0, 0);
8444         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8445         switch(vid.renderpath)
8446         {
8447         case RENDERPATH_GL11:
8448         case RENDERPATH_GL13:
8449         case RENDERPATH_GL20:
8450         case RENDERPATH_CGGL:
8451                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8452                 break;
8453         case RENDERPATH_D3D9:
8454         case RENDERPATH_D3D10:
8455         case RENDERPATH_D3D11:
8456                 break;
8457         }
8458         GL_CullFace(GL_NONE);
8459 }
8460
8461 void R_ResetViewRendering3D(void)
8462 {
8463         DrawQ_Finish();
8464
8465         R_SetupView(true);
8466         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8467         GL_Color(1, 1, 1, 1);
8468         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8469         GL_BlendFunc(GL_ONE, GL_ZERO);
8470         GL_AlphaTest(false);
8471         GL_ScissorTest(true);
8472         GL_DepthMask(true);
8473         GL_DepthRange(0, 1);
8474         GL_DepthTest(true);
8475         GL_DepthFunc(GL_LEQUAL);
8476         R_EntityMatrix(&identitymatrix);
8477         R_Mesh_ResetTextureState();
8478         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8479         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8480         switch(vid.renderpath)
8481         {
8482         case RENDERPATH_GL11:
8483         case RENDERPATH_GL13:
8484         case RENDERPATH_GL20:
8485         case RENDERPATH_CGGL:
8486                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8487                 break;
8488         case RENDERPATH_D3D9:
8489         case RENDERPATH_D3D10:
8490         case RENDERPATH_D3D11:
8491                 break;
8492         }
8493         GL_CullFace(r_refdef.view.cullface_back);
8494 }
8495
8496 /*
8497 ================
8498 R_RenderView_UpdateViewVectors
8499 ================
8500 */
8501 static void R_RenderView_UpdateViewVectors(void)
8502 {
8503         // break apart the view matrix into vectors for various purposes
8504         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8505         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8506         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8507         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8508         // make an inverted copy of the view matrix for tracking sprites
8509         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8510 }
8511
8512 void R_RenderScene(void);
8513 void R_RenderWaterPlanes(void);
8514
8515 static void R_Water_StartFrame(void)
8516 {
8517         int i;
8518         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8519         r_waterstate_waterplane_t *p;
8520
8521         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8522                 return;
8523
8524         switch(vid.renderpath)
8525         {
8526         case RENDERPATH_GL20:
8527         case RENDERPATH_CGGL:
8528         case RENDERPATH_D3D9:
8529         case RENDERPATH_D3D10:
8530         case RENDERPATH_D3D11:
8531                 break;
8532         case RENDERPATH_GL13:
8533         case RENDERPATH_GL11:
8534                 return;
8535         }
8536
8537         // set waterwidth and waterheight to the water resolution that will be
8538         // used (often less than the screen resolution for faster rendering)
8539         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8540         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8541
8542         // calculate desired texture sizes
8543         // can't use water if the card does not support the texture size
8544         if (!r_water.integer || r_showsurfaces.integer)
8545                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8546         else if (vid.support.arb_texture_non_power_of_two)
8547         {
8548                 texturewidth = waterwidth;
8549                 textureheight = waterheight;
8550                 camerawidth = waterwidth;
8551                 cameraheight = waterheight;
8552         }
8553         else
8554         {
8555                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8556                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8557                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8558                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8559         }
8560
8561         // allocate textures as needed
8562         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8563         {
8564                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8565                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8566                 {
8567                         if (p->texture_refraction)
8568                                 R_FreeTexture(p->texture_refraction);
8569                         p->texture_refraction = NULL;
8570                         if (p->texture_reflection)
8571                                 R_FreeTexture(p->texture_reflection);
8572                         p->texture_reflection = NULL;
8573                         if (p->texture_camera)
8574                                 R_FreeTexture(p->texture_camera);
8575                         p->texture_camera = NULL;
8576                 }
8577                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8578                 r_waterstate.texturewidth = texturewidth;
8579                 r_waterstate.textureheight = textureheight;
8580                 r_waterstate.camerawidth = camerawidth;
8581                 r_waterstate.cameraheight = cameraheight;
8582         }
8583
8584         if (r_waterstate.texturewidth)
8585         {
8586                 r_waterstate.enabled = true;
8587
8588                 // when doing a reduced render (HDR) we want to use a smaller area
8589                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8590                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8591
8592                 // set up variables that will be used in shader setup
8593                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8594                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8595                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8596                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8597         }
8598
8599         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8600         r_waterstate.numwaterplanes = 0;
8601 }
8602
8603 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8604 {
8605         int triangleindex, planeindex;
8606         const int *e;
8607         vec3_t vert[3];
8608         vec3_t normal;
8609         vec3_t center;
8610         mplane_t plane;
8611         r_waterstate_waterplane_t *p;
8612         texture_t *t = R_GetCurrentTexture(surface->texture);
8613
8614         // just use the first triangle with a valid normal for any decisions
8615         VectorClear(normal);
8616         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8617         {
8618                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8619                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8620                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8621                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8622                 if (VectorLength2(normal) >= 0.001)
8623                         break;
8624         }
8625
8626         VectorCopy(normal, plane.normal);
8627         VectorNormalize(plane.normal);
8628         plane.dist = DotProduct(vert[0], plane.normal);
8629         PlaneClassify(&plane);
8630         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8631         {
8632                 // skip backfaces (except if nocullface is set)
8633                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8634                         return;
8635                 VectorNegate(plane.normal, plane.normal);
8636                 plane.dist *= -1;
8637                 PlaneClassify(&plane);
8638         }
8639
8640
8641         // find a matching plane if there is one
8642         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8643                 if(p->camera_entity == t->camera_entity)
8644                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8645                                 break;
8646         if (planeindex >= r_waterstate.maxwaterplanes)
8647                 return; // nothing we can do, out of planes
8648
8649         // if this triangle does not fit any known plane rendered this frame, add one
8650         if (planeindex >= r_waterstate.numwaterplanes)
8651         {
8652                 // store the new plane
8653                 r_waterstate.numwaterplanes++;
8654                 p->plane = plane;
8655                 // clear materialflags and pvs
8656                 p->materialflags = 0;
8657                 p->pvsvalid = false;
8658                 p->camera_entity = t->camera_entity;
8659                 VectorCopy(surface->mins, p->mins);
8660                 VectorCopy(surface->maxs, p->maxs);
8661         }
8662         else
8663         {
8664                 // merge mins/maxs
8665                 p->mins[0] = min(p->mins[0], surface->mins[0]);
8666                 p->mins[1] = min(p->mins[1], surface->mins[1]);
8667                 p->mins[2] = min(p->mins[2], surface->mins[2]);
8668                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8669                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8670                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8671         }
8672         // merge this surface's materialflags into the waterplane
8673         p->materialflags |= t->currentmaterialflags;
8674         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8675         {
8676                 // merge this surface's PVS into the waterplane
8677                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8678                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8679                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8680                 {
8681                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8682                         p->pvsvalid = true;
8683                 }
8684         }
8685 }
8686
8687 static void R_Water_ProcessPlanes(void)
8688 {
8689         int myscissor[4];
8690         r_refdef_view_t originalview;
8691         r_refdef_view_t myview;
8692         int planeindex;
8693         r_waterstate_waterplane_t *p;
8694         vec3_t visorigin;
8695
8696         originalview = r_refdef.view;
8697
8698         // make sure enough textures are allocated
8699         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8700         {
8701                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8702                 {
8703                         if (!p->texture_refraction)
8704                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8705                         if (!p->texture_refraction)
8706                                 goto error;
8707                 }
8708                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8709                 {
8710                         if (!p->texture_camera)
8711                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
8712                         if (!p->texture_camera)
8713                                 goto error;
8714                 }
8715
8716                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8717                 {
8718                         if (!p->texture_reflection)
8719                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8720                         if (!p->texture_reflection)
8721                                 goto error;
8722                 }
8723         }
8724
8725         // render views
8726         r_refdef.view = originalview;
8727         r_refdef.view.showdebug = false;
8728         r_refdef.view.width = r_waterstate.waterwidth;
8729         r_refdef.view.height = r_waterstate.waterheight;
8730         r_refdef.view.useclipplane = true;
8731         myview = r_refdef.view;
8732         r_waterstate.renderingscene = true;
8733         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8734         {
8735                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8736                 {
8737                         r_refdef.view = myview;
8738                         if(r_water_scissormode.integer)
8739                         {
8740                                 R_SetupView(true);
8741                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8742                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8743                         }
8744
8745                         // render reflected scene and copy into texture
8746                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8747                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8748                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8749                         r_refdef.view.clipplane = p->plane;
8750
8751                         // reverse the cullface settings for this render
8752                         r_refdef.view.cullface_front = GL_FRONT;
8753                         r_refdef.view.cullface_back = GL_BACK;
8754                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8755                         {
8756                                 r_refdef.view.usecustompvs = true;
8757                                 if (p->pvsvalid)
8758                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8759                                 else
8760                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8761                         }
8762
8763                         R_ResetViewRendering3D();
8764                         R_ClearScreen(r_refdef.fogenabled);
8765                         if(r_water_scissormode.integer & 2)
8766                                 R_View_UpdateWithScissor(myscissor);
8767                         else
8768                                 R_View_Update();
8769                         if(r_water_scissormode.integer & 1)
8770                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8771                         R_RenderScene();
8772
8773                         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);
8774                 }
8775
8776                 // render the normal view scene and copy into texture
8777                 // (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)
8778                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8779                 {
8780                         r_refdef.view = myview;
8781                         if(r_water_scissormode.integer)
8782                         {
8783                                 R_SetupView(true);
8784                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8785                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8786                         }
8787
8788                         r_waterstate.renderingrefraction = true;
8789
8790                         r_refdef.view.clipplane = p->plane;
8791                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8792                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8793
8794                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8795                         {
8796                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8797                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8798                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8799                                 R_RenderView_UpdateViewVectors();
8800                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8801                                 {
8802                                         r_refdef.view.usecustompvs = true;
8803                                         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);
8804                                 }
8805                         }
8806
8807                         PlaneClassify(&r_refdef.view.clipplane);
8808
8809                         R_ResetViewRendering3D();
8810                         R_ClearScreen(r_refdef.fogenabled);
8811                         if(r_water_scissormode.integer & 2)
8812                                 R_View_UpdateWithScissor(myscissor);
8813                         else
8814                                 R_View_Update();
8815                         if(r_water_scissormode.integer & 1)
8816                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8817                         R_RenderScene();
8818
8819                         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);
8820                         r_waterstate.renderingrefraction = false;
8821                 }
8822                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8823                 {
8824                         r_refdef.view = myview;
8825
8826                         r_refdef.view.clipplane = p->plane;
8827                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8828                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8829
8830                         r_refdef.view.width = r_waterstate.camerawidth;
8831                         r_refdef.view.height = r_waterstate.cameraheight;
8832                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8833                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8834
8835                         if(p->camera_entity)
8836                         {
8837                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8838                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8839                         }
8840
8841                         // note: all of the view is used for displaying... so
8842                         // there is no use in scissoring
8843
8844                         // reverse the cullface settings for this render
8845                         r_refdef.view.cullface_front = GL_FRONT;
8846                         r_refdef.view.cullface_back = GL_BACK;
8847                         // also reverse the view matrix
8848                         Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, 1, -1); // this serves to invert texcoords in the result, as the copied texture is mapped the wrong way round
8849                         R_RenderView_UpdateViewVectors();
8850                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8851                         {
8852                                 r_refdef.view.usecustompvs = true;
8853                                 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);
8854                         }
8855                         
8856                         // camera needs no clipplane
8857                         r_refdef.view.useclipplane = false;
8858
8859                         PlaneClassify(&r_refdef.view.clipplane);
8860
8861                         R_ResetViewRendering3D();
8862                         R_ClearScreen(r_refdef.fogenabled);
8863                         R_View_Update();
8864                         R_RenderScene();
8865
8866                         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);
8867                         r_waterstate.renderingrefraction = false;
8868                 }
8869
8870         }
8871         r_waterstate.renderingscene = false;
8872         r_refdef.view = originalview;
8873         R_ResetViewRendering3D();
8874         R_ClearScreen(r_refdef.fogenabled);
8875         R_View_Update();
8876         return;
8877 error:
8878         r_refdef.view = originalview;
8879         r_waterstate.renderingscene = false;
8880         Cvar_SetValueQuick(&r_water, 0);
8881         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8882         return;
8883 }
8884
8885 void R_Bloom_StartFrame(void)
8886 {
8887         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8888
8889         switch(vid.renderpath)
8890         {
8891         case RENDERPATH_GL20:
8892         case RENDERPATH_CGGL:
8893         case RENDERPATH_D3D9:
8894         case RENDERPATH_D3D10:
8895         case RENDERPATH_D3D11:
8896                 break;
8897         case RENDERPATH_GL13:
8898         case RENDERPATH_GL11:
8899                 return;
8900         }
8901
8902         // set bloomwidth and bloomheight to the bloom resolution that will be
8903         // used (often less than the screen resolution for faster rendering)
8904         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8905         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8906         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8907         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8908         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8909
8910         // calculate desired texture sizes
8911         if (vid.support.arb_texture_non_power_of_two)
8912         {
8913                 screentexturewidth = r_refdef.view.width;
8914                 screentextureheight = r_refdef.view.height;
8915                 bloomtexturewidth = r_bloomstate.bloomwidth;
8916                 bloomtextureheight = r_bloomstate.bloomheight;
8917         }
8918         else
8919         {
8920                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8921                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8922                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8923                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8924         }
8925
8926         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))
8927         {
8928                 Cvar_SetValueQuick(&r_hdr, 0);
8929                 Cvar_SetValueQuick(&r_bloom, 0);
8930                 Cvar_SetValueQuick(&r_motionblur, 0);
8931                 Cvar_SetValueQuick(&r_damageblur, 0);
8932         }
8933
8934         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)))
8935                 screentexturewidth = screentextureheight = 0;
8936         if (!r_hdr.integer && !r_bloom.integer)
8937                 bloomtexturewidth = bloomtextureheight = 0;
8938
8939         // allocate textures as needed
8940         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8941         {
8942                 if (r_bloomstate.texture_screen)
8943                         R_FreeTexture(r_bloomstate.texture_screen);
8944                 r_bloomstate.texture_screen = NULL;
8945                 r_bloomstate.screentexturewidth = screentexturewidth;
8946                 r_bloomstate.screentextureheight = screentextureheight;
8947                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8948                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
8949         }
8950         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8951         {
8952                 if (r_bloomstate.texture_bloom)
8953                         R_FreeTexture(r_bloomstate.texture_bloom);
8954                 r_bloomstate.texture_bloom = NULL;
8955                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8956                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8957                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8958                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8959         }
8960
8961         // when doing a reduced render (HDR) we want to use a smaller area
8962         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8963         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8964         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8965         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8966         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8967
8968         // set up a texcoord array for the full resolution screen image
8969         // (we have to keep this around to copy back during final render)
8970         r_bloomstate.screentexcoord2f[0] = 0;
8971         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8972         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8973         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8974         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8975         r_bloomstate.screentexcoord2f[5] = 0;
8976         r_bloomstate.screentexcoord2f[6] = 0;
8977         r_bloomstate.screentexcoord2f[7] = 0;
8978
8979         // set up a texcoord array for the reduced resolution bloom image
8980         // (which will be additive blended over the screen image)
8981         r_bloomstate.bloomtexcoord2f[0] = 0;
8982         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8983         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8984         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8985         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8986         r_bloomstate.bloomtexcoord2f[5] = 0;
8987         r_bloomstate.bloomtexcoord2f[6] = 0;
8988         r_bloomstate.bloomtexcoord2f[7] = 0;
8989
8990         switch(vid.renderpath)
8991         {
8992         case RENDERPATH_GL11:
8993         case RENDERPATH_GL13:
8994         case RENDERPATH_GL20:
8995         case RENDERPATH_CGGL:
8996                 break;
8997         case RENDERPATH_D3D9:
8998         case RENDERPATH_D3D10:
8999         case RENDERPATH_D3D11:
9000                 {
9001                         int i;
9002                         for (i = 0;i < 4;i++)
9003                         {
9004                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
9005                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
9006                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
9007                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
9008                         }
9009                 }
9010                 break;
9011         }
9012
9013         if (r_hdr.integer || r_bloom.integer)
9014         {
9015                 r_bloomstate.enabled = true;
9016                 r_bloomstate.hdr = r_hdr.integer != 0;
9017         }
9018
9019         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);
9020 }
9021
9022 void R_Bloom_CopyBloomTexture(float colorscale)
9023 {
9024         r_refdef.stats.bloom++;
9025
9026         // scale down screen texture to the bloom texture size
9027         CHECKGLERROR
9028         R_SetViewport(&r_bloomstate.viewport);
9029         GL_BlendFunc(GL_ONE, GL_ZERO);
9030         GL_Color(colorscale, colorscale, colorscale, 1);
9031         // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
9032         switch(vid.renderpath)
9033         {
9034         case RENDERPATH_GL11:
9035         case RENDERPATH_GL13:
9036         case RENDERPATH_GL20:
9037         case RENDERPATH_CGGL:
9038                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9039                 break;
9040         case RENDERPATH_D3D9:
9041         case RENDERPATH_D3D10:
9042         case RENDERPATH_D3D11:
9043                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9044                 break;
9045         }
9046         // TODO: do boxfilter scale-down in shader?
9047         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9048         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9049         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9050
9051         // we now have a bloom image in the framebuffer
9052         // copy it into the bloom image texture for later processing
9053         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);
9054         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9055 }
9056
9057 void R_Bloom_CopyHDRTexture(void)
9058 {
9059         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);
9060         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9061 }
9062
9063 void R_Bloom_MakeTexture(void)
9064 {
9065         int x, range, dir;
9066         float xoffset, yoffset, r, brighten;
9067
9068         r_refdef.stats.bloom++;
9069
9070         R_ResetViewRendering2D();
9071
9072         // we have a bloom image in the framebuffer
9073         CHECKGLERROR
9074         R_SetViewport(&r_bloomstate.viewport);
9075
9076         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9077         {
9078                 x *= 2;
9079                 r = bound(0, r_bloom_colorexponent.value / x, 1);
9080                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9081                 GL_Color(r,r,r,1);
9082                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9083                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9084                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9085                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9086
9087                 // copy the vertically blurred bloom view to a texture
9088                 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);
9089                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9090         }
9091
9092         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9093         brighten = r_bloom_brighten.value;
9094         if (r_hdr.integer)
9095                 brighten *= r_hdr_range.value;
9096         brighten = sqrt(brighten);
9097         if(range >= 1)
9098                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9099         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9100
9101         for (dir = 0;dir < 2;dir++)
9102         {
9103                 // blend on at multiple vertical offsets to achieve a vertical blur
9104                 // TODO: do offset blends using GLSL
9105                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9106                 GL_BlendFunc(GL_ONE, GL_ZERO);
9107                 for (x = -range;x <= range;x++)
9108                 {
9109                         if (!dir){xoffset = 0;yoffset = x;}
9110                         else {xoffset = x;yoffset = 0;}
9111                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
9112                         yoffset /= (float)r_bloomstate.bloomtextureheight;
9113                         // compute a texcoord array with the specified x and y offset
9114                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9115                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9116                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9117                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9118                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9119                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9120                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9121                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9122                         // this r value looks like a 'dot' particle, fading sharply to
9123                         // black at the edges
9124                         // (probably not realistic but looks good enough)
9125                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9126                         //r = brighten/(range*2+1);
9127                         r = brighten / (range * 2 + 1);
9128                         if(range >= 1)
9129                                 r *= (1 - x*x/(float)(range*range));
9130                         GL_Color(r, r, r, 1);
9131                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9132                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9133                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9134                         GL_BlendFunc(GL_ONE, GL_ONE);
9135                 }
9136
9137                 // copy the vertically blurred bloom view to a texture
9138                 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);
9139                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9140         }
9141 }
9142
9143 void R_HDR_RenderBloomTexture(void)
9144 {
9145         int oldwidth, oldheight;
9146         float oldcolorscale;
9147
9148         oldcolorscale = r_refdef.view.colorscale;
9149         oldwidth = r_refdef.view.width;
9150         oldheight = r_refdef.view.height;
9151         r_refdef.view.width = r_bloomstate.bloomwidth;
9152         r_refdef.view.height = r_bloomstate.bloomheight;
9153
9154         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
9155         // TODO: add exposure compensation features
9156         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9157
9158         r_refdef.view.showdebug = false;
9159         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9160
9161         R_ResetViewRendering3D();
9162
9163         R_ClearScreen(r_refdef.fogenabled);
9164         if (r_timereport_active)
9165                 R_TimeReport("HDRclear");
9166
9167         R_View_Update();
9168         if (r_timereport_active)
9169                 R_TimeReport("visibility");
9170
9171         // only do secondary renders with HDR if r_hdr is 2 or higher
9172         r_waterstate.numwaterplanes = 0;
9173         if (r_waterstate.enabled && r_hdr.integer >= 2)
9174                 R_RenderWaterPlanes();
9175
9176         r_refdef.view.showdebug = true;
9177         R_RenderScene();
9178         r_waterstate.numwaterplanes = 0;
9179
9180         R_ResetViewRendering2D();
9181
9182         R_Bloom_CopyHDRTexture();
9183         R_Bloom_MakeTexture();
9184
9185         // restore the view settings
9186         r_refdef.view.width = oldwidth;
9187         r_refdef.view.height = oldheight;
9188         r_refdef.view.colorscale = oldcolorscale;
9189
9190         R_ResetViewRendering3D();
9191
9192         R_ClearScreen(r_refdef.fogenabled);
9193         if (r_timereport_active)
9194                 R_TimeReport("viewclear");
9195 }
9196
9197 static void R_BlendView(void)
9198 {
9199         unsigned int permutation;
9200         float uservecs[4][4];
9201
9202         switch (vid.renderpath)
9203         {
9204         case RENDERPATH_GL20:
9205         case RENDERPATH_CGGL:
9206         case RENDERPATH_D3D9:
9207         case RENDERPATH_D3D10:
9208         case RENDERPATH_D3D11:
9209                 permutation =
9210                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9211                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9212                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9213                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9214                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9215
9216                 if (r_bloomstate.texture_screen)
9217                 {
9218                         // make sure the buffer is available
9219                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9220
9221                         R_ResetViewRendering2D();
9222
9223                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9224                         {
9225                                 // declare variables
9226                                 float speed;
9227                                 static float avgspeed;
9228
9229                                 speed = VectorLength(cl.movement_velocity);
9230
9231                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9232                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9233
9234                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9235                                 speed = bound(0, speed, 1);
9236                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9237
9238                                 // calculate values into a standard alpha
9239                                 cl.motionbluralpha = 1 - exp(-
9240                                                 (
9241                                                  (r_motionblur.value * speed / 80)
9242                                                  +
9243                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9244                                                 )
9245                                                 /
9246                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
9247                                            );
9248
9249                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9250                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9251                                 // apply the blur
9252                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9253                                 {
9254                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9255                                         GL_Color(1, 1, 1, cl.motionbluralpha);
9256                                         switch(vid.renderpath)
9257                                         {
9258                                         case RENDERPATH_GL11:
9259                                         case RENDERPATH_GL13:
9260                                         case RENDERPATH_GL20:
9261                                         case RENDERPATH_CGGL:
9262                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9263                                                 break;
9264                                         case RENDERPATH_D3D9:
9265                                         case RENDERPATH_D3D10:
9266                                         case RENDERPATH_D3D11:
9267                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9268                                                 break;
9269                                         }
9270                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9271                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9272                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9273                                 }
9274                         }
9275
9276                         // copy view into the screen texture
9277                         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);
9278                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9279                 }
9280                 else if (!r_bloomstate.texture_bloom)
9281                 {
9282                         // we may still have to do view tint...
9283                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9284                         {
9285                                 // apply a color tint to the whole view
9286                                 R_ResetViewRendering2D();
9287                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9288                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9289                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9290                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9291                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9292                         }
9293                         break; // no screen processing, no bloom, skip it
9294                 }
9295
9296                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9297                 {
9298                         // render simple bloom effect
9299                         // copy the screen and shrink it and darken it for the bloom process
9300                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9301                         // make the bloom texture
9302                         R_Bloom_MakeTexture();
9303                 }
9304
9305 #if _MSC_VER >= 1400
9306 #define sscanf sscanf_s
9307 #endif
9308                 memset(uservecs, 0, sizeof(uservecs));
9309                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9310                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9311                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9312                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9313
9314                 R_ResetViewRendering2D();
9315                 GL_Color(1, 1, 1, 1);
9316                 GL_BlendFunc(GL_ONE, GL_ZERO);
9317
9318                 switch(vid.renderpath)
9319                 {
9320                 case RENDERPATH_GL20:
9321                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9322                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9323                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9324                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9325                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9326                         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]);
9327                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9328                         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]);
9329                         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]);
9330                         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]);
9331                         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]);
9332                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9333                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9334                         if (r_glsl_permutation->loc_BloomColorSubtract    >= 0) qglUniform4fARB(r_glsl_permutation->loc_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9335                         break;
9336                 case RENDERPATH_CGGL:
9337 #ifdef SUPPORTCG
9338                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9339                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9340                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9341                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9342                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9343                         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
9344                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9345                         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
9346                         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
9347                         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
9348                         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
9349                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9350                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9351                         if (r_cg_permutation->fp_BloomColorSubtract   ) cgGLSetParameter4f(r_cg_permutation->fp_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9352 #endif
9353                         break;
9354                 case RENDERPATH_D3D9:
9355 #ifdef SUPPORTD3D
9356                         // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
9357                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9358                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9359                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9360                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9361                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9362                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9363                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9364                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9365                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9366                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9367                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9368                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9369                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9370                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9371 #endif
9372                         break;
9373                 case RENDERPATH_D3D10:
9374                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9375                         break;
9376                 case RENDERPATH_D3D11:
9377                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9378                         break;
9379                 default:
9380                         break;
9381                 }
9382                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9383                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9384                 break;
9385         case RENDERPATH_GL13:
9386         case RENDERPATH_GL11:
9387                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9388                 {
9389                         // apply a color tint to the whole view
9390                         R_ResetViewRendering2D();
9391                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9392                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9393                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9394                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9395                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9396                 }
9397                 break;
9398         }
9399 }
9400
9401 matrix4x4_t r_waterscrollmatrix;
9402
9403 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9404 {
9405         if (r_refdef.fog_density)
9406         {
9407                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9408                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9409                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9410
9411                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9412                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9413                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9414                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9415
9416                 {
9417                         vec3_t fogvec;
9418                         VectorCopy(r_refdef.fogcolor, fogvec);
9419                         //   color.rgb *= ContrastBoost * SceneBrightness;
9420                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9421                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9422                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9423                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9424                 }
9425         }
9426 }
9427
9428 void R_UpdateVariables(void)
9429 {
9430         R_Textures_Frame();
9431
9432         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9433
9434         r_refdef.farclip = r_farclip_base.value;
9435         if (r_refdef.scene.worldmodel)
9436                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9437         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9438
9439         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9440                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9441         r_refdef.polygonfactor = 0;
9442         r_refdef.polygonoffset = 0;
9443         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9444         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9445
9446         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9447         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9448         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9449         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9450         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9451         if (FAKELIGHT_ENABLED)
9452         {
9453                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9454         }
9455         if (r_showsurfaces.integer)
9456         {
9457                 r_refdef.scene.rtworld = false;
9458                 r_refdef.scene.rtworldshadows = false;
9459                 r_refdef.scene.rtdlight = false;
9460                 r_refdef.scene.rtdlightshadows = false;
9461                 r_refdef.lightmapintensity = 0;
9462         }
9463
9464         if (gamemode == GAME_NEHAHRA)
9465         {
9466                 if (gl_fogenable.integer)
9467                 {
9468                         r_refdef.oldgl_fogenable = true;
9469                         r_refdef.fog_density = gl_fogdensity.value;
9470                         r_refdef.fog_red = gl_fogred.value;
9471                         r_refdef.fog_green = gl_foggreen.value;
9472                         r_refdef.fog_blue = gl_fogblue.value;
9473                         r_refdef.fog_alpha = 1;
9474                         r_refdef.fog_start = 0;
9475                         r_refdef.fog_end = gl_skyclip.value;
9476                         r_refdef.fog_height = 1<<30;
9477                         r_refdef.fog_fadedepth = 128;
9478                 }
9479                 else if (r_refdef.oldgl_fogenable)
9480                 {
9481                         r_refdef.oldgl_fogenable = false;
9482                         r_refdef.fog_density = 0;
9483                         r_refdef.fog_red = 0;
9484                         r_refdef.fog_green = 0;
9485                         r_refdef.fog_blue = 0;
9486                         r_refdef.fog_alpha = 0;
9487                         r_refdef.fog_start = 0;
9488                         r_refdef.fog_end = 0;
9489                         r_refdef.fog_height = 1<<30;
9490                         r_refdef.fog_fadedepth = 128;
9491                 }
9492         }
9493
9494         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9495         r_refdef.fog_start = max(0, r_refdef.fog_start);
9496         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9497
9498         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9499
9500         if (r_refdef.fog_density && r_drawfog.integer)
9501         {
9502                 r_refdef.fogenabled = true;
9503                 // this is the point where the fog reaches 0.9986 alpha, which we
9504                 // consider a good enough cutoff point for the texture
9505                 // (0.9986 * 256 == 255.6)
9506                 if (r_fog_exp2.integer)
9507                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9508                 else
9509                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9510                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9511                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9512                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9513                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9514                         R_BuildFogHeightTexture();
9515                 // fog color was already set
9516                 // update the fog texture
9517                 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)
9518                         R_BuildFogTexture();
9519                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9520                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9521         }
9522         else
9523                 r_refdef.fogenabled = false;
9524
9525         switch(vid.renderpath)
9526         {
9527         case RENDERPATH_GL20:
9528         case RENDERPATH_CGGL:
9529         case RENDERPATH_D3D9:
9530         case RENDERPATH_D3D10:
9531         case RENDERPATH_D3D11:
9532                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9533                 {
9534                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9535                         {
9536                                 // build GLSL gamma texture
9537 #define RAMPWIDTH 256
9538                                 unsigned short ramp[RAMPWIDTH * 3];
9539                                 unsigned char rampbgr[RAMPWIDTH][4];
9540                                 int i;
9541
9542                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9543
9544                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9545                                 for(i = 0; i < RAMPWIDTH; ++i)
9546                                 {
9547                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9548                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9549                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9550                                         rampbgr[i][3] = 0;
9551                                 }
9552                                 if (r_texture_gammaramps)
9553                                 {
9554                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9555                                 }
9556                                 else
9557                                 {
9558                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9559                                 }
9560                         }
9561                 }
9562                 else
9563                 {
9564                         // remove GLSL gamma texture
9565                 }
9566                 break;
9567         case RENDERPATH_GL13:
9568         case RENDERPATH_GL11:
9569                 break;
9570         }
9571 }
9572
9573 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9574 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9575 /*
9576 ================
9577 R_SelectScene
9578 ================
9579 */
9580 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9581         if( scenetype != r_currentscenetype ) {
9582                 // store the old scenetype
9583                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9584                 r_currentscenetype = scenetype;
9585                 // move in the new scene
9586                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9587         }
9588 }
9589
9590 /*
9591 ================
9592 R_GetScenePointer
9593 ================
9594 */
9595 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9596 {
9597         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9598         if( scenetype == r_currentscenetype ) {
9599                 return &r_refdef.scene;
9600         } else {
9601                 return &r_scenes_store[ scenetype ];
9602         }
9603 }
9604
9605 /*
9606 ================
9607 R_RenderView
9608 ================
9609 */
9610 void R_RenderView(void)
9611 {
9612         if (r_timereport_active)
9613                 R_TimeReport("start");
9614         r_textureframe++; // used only by R_GetCurrentTexture
9615         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9616
9617         if(R_CompileShader_CheckStaticParms())
9618                 R_GLSL_Restart_f();
9619
9620         if (!r_drawentities.integer)
9621                 r_refdef.scene.numentities = 0;
9622
9623         R_AnimCache_ClearCache();
9624         R_FrameData_NewFrame();
9625
9626         if (r_refdef.view.isoverlay)
9627         {
9628                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9629                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9630                 R_TimeReport("depthclear");
9631
9632                 r_refdef.view.showdebug = false;
9633
9634                 r_waterstate.enabled = false;
9635                 r_waterstate.numwaterplanes = 0;
9636
9637                 R_RenderScene();
9638
9639                 CHECKGLERROR
9640                 return;
9641         }
9642
9643         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9644                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9645
9646         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9647
9648         R_RenderView_UpdateViewVectors();
9649
9650         R_Shadow_UpdateWorldLightSelection();
9651
9652         R_Bloom_StartFrame();
9653         R_Water_StartFrame();
9654
9655         CHECKGLERROR
9656         if (r_timereport_active)
9657                 R_TimeReport("viewsetup");
9658
9659         R_ResetViewRendering3D();
9660
9661         if (r_refdef.view.clear || r_refdef.fogenabled)
9662         {
9663                 R_ClearScreen(r_refdef.fogenabled);
9664                 if (r_timereport_active)
9665                         R_TimeReport("viewclear");
9666         }
9667         r_refdef.view.clear = true;
9668
9669         // this produces a bloom texture to be used in R_BlendView() later
9670         if (r_hdr.integer && r_bloomstate.bloomwidth)
9671         {
9672                 R_HDR_RenderBloomTexture();
9673                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9674                 r_textureframe++; // used only by R_GetCurrentTexture
9675         }
9676
9677         r_refdef.view.showdebug = true;
9678
9679         R_View_Update();
9680         if (r_timereport_active)
9681                 R_TimeReport("visibility");
9682
9683         r_waterstate.numwaterplanes = 0;
9684         if (r_waterstate.enabled)
9685                 R_RenderWaterPlanes();
9686
9687         R_RenderScene();
9688         r_waterstate.numwaterplanes = 0;
9689
9690         R_BlendView();
9691         if (r_timereport_active)
9692                 R_TimeReport("blendview");
9693
9694         GL_Scissor(0, 0, vid.width, vid.height);
9695         GL_ScissorTest(false);
9696
9697         CHECKGLERROR
9698 }
9699
9700 void R_RenderWaterPlanes(void)
9701 {
9702         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9703         {
9704                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9705                 if (r_timereport_active)
9706                         R_TimeReport("waterworld");
9707         }
9708
9709         // don't let sound skip if going slow
9710         if (r_refdef.scene.extraupdate)
9711                 S_ExtraUpdate ();
9712
9713         R_DrawModelsAddWaterPlanes();
9714         if (r_timereport_active)
9715                 R_TimeReport("watermodels");
9716
9717         if (r_waterstate.numwaterplanes)
9718         {
9719                 R_Water_ProcessPlanes();
9720                 if (r_timereport_active)
9721                         R_TimeReport("waterscenes");
9722         }
9723 }
9724
9725 extern void R_DrawLightningBeams (void);
9726 extern void VM_CL_AddPolygonsToMeshQueue (void);
9727 extern void R_DrawPortals (void);
9728 extern cvar_t cl_locs_show;
9729 static void R_DrawLocs(void);
9730 static void R_DrawEntityBBoxes(void);
9731 static void R_DrawModelDecals(void);
9732 extern void R_DrawModelShadows(void);
9733 extern void R_DrawModelShadowMaps(void);
9734 extern cvar_t cl_decals_newsystem;
9735 extern qboolean r_shadow_usingdeferredprepass;
9736 void R_RenderScene(void)
9737 {
9738         qboolean shadowmapping = false;
9739
9740         if (r_timereport_active)
9741                 R_TimeReport("beginscene");
9742
9743         r_refdef.stats.renders++;
9744
9745         R_UpdateFogColor();
9746
9747         // don't let sound skip if going slow
9748         if (r_refdef.scene.extraupdate)
9749                 S_ExtraUpdate ();
9750
9751         R_MeshQueue_BeginScene();
9752
9753         R_SkyStartFrame();
9754
9755         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);
9756
9757         if (r_timereport_active)
9758                 R_TimeReport("skystartframe");
9759
9760         if (cl.csqc_vidvars.drawworld)
9761         {
9762                 // don't let sound skip if going slow
9763                 if (r_refdef.scene.extraupdate)
9764                         S_ExtraUpdate ();
9765
9766                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9767                 {
9768                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9769                         if (r_timereport_active)
9770                                 R_TimeReport("worldsky");
9771                 }
9772
9773                 if (R_DrawBrushModelsSky() && r_timereport_active)
9774                         R_TimeReport("bmodelsky");
9775
9776                 if (skyrendermasked && skyrenderlater)
9777                 {
9778                         // we have to force off the water clipping plane while rendering sky
9779                         R_SetupView(false);
9780                         R_Sky();
9781                         R_SetupView(true);
9782                         if (r_timereport_active)
9783                                 R_TimeReport("sky");
9784                 }
9785         }
9786
9787         R_AnimCache_CacheVisibleEntities();
9788         if (r_timereport_active)
9789                 R_TimeReport("animation");
9790
9791         R_Shadow_PrepareLights();
9792         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9793                 R_Shadow_PrepareModelShadows();
9794         if (r_timereport_active)
9795                 R_TimeReport("preparelights");
9796
9797         if (R_Shadow_ShadowMappingEnabled())
9798                 shadowmapping = true;
9799
9800         if (r_shadow_usingdeferredprepass)
9801                 R_Shadow_DrawPrepass();
9802
9803         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9804         {
9805                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9806                 if (r_timereport_active)
9807                         R_TimeReport("worlddepth");
9808         }
9809         if (r_depthfirst.integer >= 2)
9810         {
9811                 R_DrawModelsDepth();
9812                 if (r_timereport_active)
9813                         R_TimeReport("modeldepth");
9814         }
9815
9816         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9817         {
9818                 R_DrawModelShadowMaps();
9819                 R_ResetViewRendering3D();
9820                 // don't let sound skip if going slow
9821                 if (r_refdef.scene.extraupdate)
9822                         S_ExtraUpdate ();
9823         }
9824
9825         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9826         {
9827                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9828                 if (r_timereport_active)
9829                         R_TimeReport("world");
9830         }
9831
9832         // don't let sound skip if going slow
9833         if (r_refdef.scene.extraupdate)
9834                 S_ExtraUpdate ();
9835
9836         R_DrawModels();
9837         if (r_timereport_active)
9838                 R_TimeReport("models");
9839
9840         // don't let sound skip if going slow
9841         if (r_refdef.scene.extraupdate)
9842                 S_ExtraUpdate ();
9843
9844         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9845         {
9846                 R_DrawModelShadows();
9847                 R_ResetViewRendering3D();
9848                 // don't let sound skip if going slow
9849                 if (r_refdef.scene.extraupdate)
9850                         S_ExtraUpdate ();
9851         }
9852
9853         if (!r_shadow_usingdeferredprepass)
9854         {
9855                 R_Shadow_DrawLights();
9856                 if (r_timereport_active)
9857                         R_TimeReport("rtlights");
9858         }
9859
9860         // don't let sound skip if going slow
9861         if (r_refdef.scene.extraupdate)
9862                 S_ExtraUpdate ();
9863
9864         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9865         {
9866                 R_DrawModelShadows();
9867                 R_ResetViewRendering3D();
9868                 // don't let sound skip if going slow
9869                 if (r_refdef.scene.extraupdate)
9870                         S_ExtraUpdate ();
9871         }
9872
9873         if (cl.csqc_vidvars.drawworld)
9874         {
9875                 if (cl_decals_newsystem.integer)
9876                 {
9877                         R_DrawModelDecals();
9878                         if (r_timereport_active)
9879                                 R_TimeReport("modeldecals");
9880                 }
9881                 else
9882                 {
9883                         R_DrawDecals();
9884                         if (r_timereport_active)
9885                                 R_TimeReport("decals");
9886                 }
9887
9888                 R_DrawParticles();
9889                 if (r_timereport_active)
9890                         R_TimeReport("particles");
9891
9892                 R_DrawExplosions();
9893                 if (r_timereport_active)
9894                         R_TimeReport("explosions");
9895
9896                 R_DrawLightningBeams();
9897                 if (r_timereport_active)
9898                         R_TimeReport("lightning");
9899         }
9900
9901         VM_CL_AddPolygonsToMeshQueue();
9902
9903         if (r_refdef.view.showdebug)
9904         {
9905                 if (cl_locs_show.integer)
9906                 {
9907                         R_DrawLocs();
9908                         if (r_timereport_active)
9909                                 R_TimeReport("showlocs");
9910                 }
9911
9912                 if (r_drawportals.integer)
9913                 {
9914                         R_DrawPortals();
9915                         if (r_timereport_active)
9916                                 R_TimeReport("portals");
9917                 }
9918
9919                 if (r_showbboxes.value > 0)
9920                 {
9921                         R_DrawEntityBBoxes();
9922                         if (r_timereport_active)
9923                                 R_TimeReport("bboxes");
9924                 }
9925         }
9926
9927         R_MeshQueue_RenderTransparent();
9928         if (r_timereport_active)
9929                 R_TimeReport("drawtrans");
9930
9931         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))
9932         {
9933                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9934                 if (r_timereport_active)
9935                         R_TimeReport("worlddebug");
9936                 R_DrawModelsDebug();
9937                 if (r_timereport_active)
9938                         R_TimeReport("modeldebug");
9939         }
9940
9941         if (cl.csqc_vidvars.drawworld)
9942         {
9943                 R_Shadow_DrawCoronas();
9944                 if (r_timereport_active)
9945                         R_TimeReport("coronas");
9946         }
9947
9948 #if 0
9949         {
9950                 GL_DepthTest(false);
9951                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9952                 GL_Color(1, 1, 1, 1);
9953                 qglBegin(GL_POLYGON);
9954                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9955                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9956                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9957                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9958                 qglEnd();
9959                 qglBegin(GL_POLYGON);
9960                 qglVertex3f(r_refdef.view.frustumcorner[0][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[0][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[0][2] + 1000 * r_refdef.view.forward[2]);
9961                 qglVertex3f(r_refdef.view.frustumcorner[1][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[1][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[1][2] + 1000 * r_refdef.view.forward[2]);
9962                 qglVertex3f(r_refdef.view.frustumcorner[3][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[3][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[3][2] + 1000 * r_refdef.view.forward[2]);
9963                 qglVertex3f(r_refdef.view.frustumcorner[2][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[2][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[2][2] + 1000 * r_refdef.view.forward[2]);
9964                 qglEnd();
9965                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9966         }
9967 #endif
9968
9969         // don't let sound skip if going slow
9970         if (r_refdef.scene.extraupdate)
9971                 S_ExtraUpdate ();
9972
9973         R_ResetViewRendering2D();
9974 }
9975
9976 static const unsigned short bboxelements[36] =
9977 {
9978         5, 1, 3, 5, 3, 7,
9979         6, 2, 0, 6, 0, 4,
9980         7, 3, 2, 7, 2, 6,
9981         4, 0, 1, 4, 1, 5,
9982         4, 5, 7, 4, 7, 6,
9983         1, 0, 2, 1, 2, 3,
9984 };
9985
9986 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9987 {
9988         int i;
9989         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9990
9991         RSurf_ActiveWorldEntity();
9992
9993         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9994         GL_DepthMask(false);
9995         GL_DepthRange(0, 1);
9996         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9997         R_Mesh_ResetTextureState();
9998
9999         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
10000         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
10001         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
10002         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
10003         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
10004         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
10005         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
10006         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
10007         R_FillColors(color4f, 8, cr, cg, cb, ca);
10008         if (r_refdef.fogenabled)
10009         {
10010                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
10011                 {
10012                         f1 = RSurf_FogVertex(v);
10013                         f2 = 1 - f1;
10014                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
10015                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
10016                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
10017                 }
10018         }
10019         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
10020         R_Mesh_ResetTextureState();
10021         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10022         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
10023 }
10024
10025 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10026 {
10027         int i;
10028         float color[4];
10029         prvm_edict_t *edict;
10030         prvm_prog_t *prog_save = prog;
10031
10032         // this function draws bounding boxes of server entities
10033         if (!sv.active)
10034                 return;
10035
10036         GL_CullFace(GL_NONE);
10037         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10038
10039         prog = 0;
10040         SV_VM_Begin();
10041         for (i = 0;i < numsurfaces;i++)
10042         {
10043                 edict = PRVM_EDICT_NUM(surfacelist[i]);
10044                 switch ((int)edict->fields.server->solid)
10045                 {
10046                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
10047                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
10048                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
10049                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
10050                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
10051                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
10052                 }
10053                 color[3] *= r_showbboxes.value;
10054                 color[3] = bound(0, color[3], 1);
10055                 GL_DepthTest(!r_showdisabledepthtest.integer);
10056                 GL_CullFace(r_refdef.view.cullface_front);
10057                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10058         }
10059         SV_VM_End();
10060         prog = prog_save;
10061 }
10062
10063 static void R_DrawEntityBBoxes(void)
10064 {
10065         int i;
10066         prvm_edict_t *edict;
10067         vec3_t center;
10068         prvm_prog_t *prog_save = prog;
10069
10070         // this function draws bounding boxes of server entities
10071         if (!sv.active)
10072                 return;
10073
10074         prog = 0;
10075         SV_VM_Begin();
10076         for (i = 0;i < prog->num_edicts;i++)
10077         {
10078                 edict = PRVM_EDICT_NUM(i);
10079                 if (edict->priv.server->free)
10080                         continue;
10081                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10082                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10083                         continue;
10084                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10085                         continue;
10086                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10087                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10088         }
10089         SV_VM_End();
10090         prog = prog_save;
10091 }
10092
10093 static const int nomodelelement3i[24] =
10094 {
10095         5, 2, 0,
10096         5, 1, 2,
10097         5, 0, 3,
10098         5, 3, 1,
10099         0, 2, 4,
10100         2, 1, 4,
10101         3, 0, 4,
10102         1, 3, 4
10103 };
10104
10105 static const unsigned short nomodelelement3s[24] =
10106 {
10107         5, 2, 0,
10108         5, 1, 2,
10109         5, 0, 3,
10110         5, 3, 1,
10111         0, 2, 4,
10112         2, 1, 4,
10113         3, 0, 4,
10114         1, 3, 4
10115 };
10116
10117 static const float nomodelvertex3f[6*3] =
10118 {
10119         -16,   0,   0,
10120          16,   0,   0,
10121           0, -16,   0,
10122           0,  16,   0,
10123           0,   0, -16,
10124           0,   0,  16
10125 };
10126
10127 static const float nomodelcolor4f[6*4] =
10128 {
10129         0.0f, 0.0f, 0.5f, 1.0f,
10130         0.0f, 0.0f, 0.5f, 1.0f,
10131         0.0f, 0.5f, 0.0f, 1.0f,
10132         0.0f, 0.5f, 0.0f, 1.0f,
10133         0.5f, 0.0f, 0.0f, 1.0f,
10134         0.5f, 0.0f, 0.0f, 1.0f
10135 };
10136
10137 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10138 {
10139         int i;
10140         float f1, f2, *c;
10141         float color4f[6*4];
10142
10143         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);
10144
10145         // this is only called once per entity so numsurfaces is always 1, and
10146         // surfacelist is always {0}, so this code does not handle batches
10147
10148         if (rsurface.ent_flags & RENDER_ADDITIVE)
10149         {
10150                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10151                 GL_DepthMask(false);
10152         }
10153         else if (rsurface.colormod[3] < 1)
10154         {
10155                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10156                 GL_DepthMask(false);
10157         }
10158         else
10159         {
10160                 GL_BlendFunc(GL_ONE, GL_ZERO);
10161                 GL_DepthMask(true);
10162         }
10163         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10164         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10165         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10166         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10167         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10168         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10169         for (i = 0, c = color4f;i < 6;i++, c += 4)
10170         {
10171                 c[0] *= rsurface.colormod[0];
10172                 c[1] *= rsurface.colormod[1];
10173                 c[2] *= rsurface.colormod[2];
10174                 c[3] *= rsurface.colormod[3];
10175         }
10176         if (r_refdef.fogenabled)
10177         {
10178                 for (i = 0, c = color4f;i < 6;i++, c += 4)
10179                 {
10180                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10181                         f2 = 1 - f1;
10182                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10183                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10184                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10185                 }
10186         }
10187         R_Mesh_ResetTextureState();
10188         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10189         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10190 }
10191
10192 void R_DrawNoModel(entity_render_t *ent)
10193 {
10194         vec3_t org;
10195         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10196         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10197                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10198         else
10199                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10200 }
10201
10202 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10203 {
10204         vec3_t right1, right2, diff, normal;
10205
10206         VectorSubtract (org2, org1, normal);
10207
10208         // calculate 'right' vector for start
10209         VectorSubtract (r_refdef.view.origin, org1, diff);
10210         CrossProduct (normal, diff, right1);
10211         VectorNormalize (right1);
10212
10213         // calculate 'right' vector for end
10214         VectorSubtract (r_refdef.view.origin, org2, diff);
10215         CrossProduct (normal, diff, right2);
10216         VectorNormalize (right2);
10217
10218         vert[ 0] = org1[0] + width * right1[0];
10219         vert[ 1] = org1[1] + width * right1[1];
10220         vert[ 2] = org1[2] + width * right1[2];
10221         vert[ 3] = org1[0] - width * right1[0];
10222         vert[ 4] = org1[1] - width * right1[1];
10223         vert[ 5] = org1[2] - width * right1[2];
10224         vert[ 6] = org2[0] - width * right2[0];
10225         vert[ 7] = org2[1] - width * right2[1];
10226         vert[ 8] = org2[2] - width * right2[2];
10227         vert[ 9] = org2[0] + width * right2[0];
10228         vert[10] = org2[1] + width * right2[1];
10229         vert[11] = org2[2] + width * right2[2];
10230 }
10231
10232 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)
10233 {
10234         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10235         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10236         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10237         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10238         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10239         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10240         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10241         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10242         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10243         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10244         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10245         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10246 }
10247
10248 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10249 {
10250         int i;
10251         float *vertex3f;
10252         float v[3];
10253         VectorSet(v, x, y, z);
10254         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10255                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10256                         break;
10257         if (i == mesh->numvertices)
10258         {
10259                 if (mesh->numvertices < mesh->maxvertices)
10260                 {
10261                         VectorCopy(v, vertex3f);
10262                         mesh->numvertices++;
10263                 }
10264                 return mesh->numvertices;
10265         }
10266         else
10267                 return i;
10268 }
10269
10270 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10271 {
10272         int i;
10273         int *e, element[3];
10274         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10275         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10276         e = mesh->element3i + mesh->numtriangles * 3;
10277         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10278         {
10279                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10280                 if (mesh->numtriangles < mesh->maxtriangles)
10281                 {
10282                         *e++ = element[0];
10283                         *e++ = element[1];
10284                         *e++ = element[2];
10285                         mesh->numtriangles++;
10286                 }
10287                 element[1] = element[2];
10288         }
10289 }
10290
10291 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10292 {
10293         int i;
10294         int *e, element[3];
10295         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10296         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10297         e = mesh->element3i + mesh->numtriangles * 3;
10298         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10299         {
10300                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10301                 if (mesh->numtriangles < mesh->maxtriangles)
10302                 {
10303                         *e++ = element[0];
10304                         *e++ = element[1];
10305                         *e++ = element[2];
10306                         mesh->numtriangles++;
10307                 }
10308                 element[1] = element[2];
10309         }
10310 }
10311
10312 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10313 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10314 {
10315         int planenum, planenum2;
10316         int w;
10317         int tempnumpoints;
10318         mplane_t *plane, *plane2;
10319         double maxdist;
10320         double temppoints[2][256*3];
10321         // figure out how large a bounding box we need to properly compute this brush
10322         maxdist = 0;
10323         for (w = 0;w < numplanes;w++)
10324                 maxdist = max(maxdist, fabs(planes[w].dist));
10325         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10326         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10327         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10328         {
10329                 w = 0;
10330                 tempnumpoints = 4;
10331                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10332                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10333                 {
10334                         if (planenum2 == planenum)
10335                                 continue;
10336                         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);
10337                         w = !w;
10338                 }
10339                 if (tempnumpoints < 3)
10340                         continue;
10341                 // generate elements forming a triangle fan for this polygon
10342                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10343         }
10344 }
10345
10346 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)
10347 {
10348         texturelayer_t *layer;
10349         layer = t->currentlayers + t->currentnumlayers++;
10350         layer->type = type;
10351         layer->depthmask = depthmask;
10352         layer->blendfunc1 = blendfunc1;
10353         layer->blendfunc2 = blendfunc2;
10354         layer->texture = texture;
10355         layer->texmatrix = *matrix;
10356         layer->color[0] = r;
10357         layer->color[1] = g;
10358         layer->color[2] = b;
10359         layer->color[3] = a;
10360 }
10361
10362 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10363 {
10364         if(parms[0] == 0 && parms[1] == 0)
10365                 return false;
10366         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10367                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10368                         return false;
10369         return true;
10370 }
10371
10372 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10373 {
10374         double index, f;
10375         index = parms[2] + r_refdef.scene.time * parms[3];
10376         index -= floor(index);
10377         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10378         {
10379         default:
10380         case Q3WAVEFUNC_NONE:
10381         case Q3WAVEFUNC_NOISE:
10382         case Q3WAVEFUNC_COUNT:
10383                 f = 0;
10384                 break;
10385         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10386         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10387         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10388         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10389         case Q3WAVEFUNC_TRIANGLE:
10390                 index *= 4;
10391                 f = index - floor(index);
10392                 if (index < 1)
10393                         f = f;
10394                 else if (index < 2)
10395                         f = 1 - f;
10396                 else if (index < 3)
10397                         f = -f;
10398                 else
10399                         f = -(1 - f);
10400                 break;
10401         }
10402         f = parms[0] + parms[1] * f;
10403         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10404                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10405         return (float) f;
10406 }
10407
10408 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10409 {
10410         int w, h, idx;
10411         float f;
10412         float tcmat[12];
10413         matrix4x4_t matrix, temp;
10414         switch(tcmod->tcmod)
10415         {
10416                 case Q3TCMOD_COUNT:
10417                 case Q3TCMOD_NONE:
10418                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10419                                 matrix = r_waterscrollmatrix;
10420                         else
10421                                 matrix = identitymatrix;
10422                         break;
10423                 case Q3TCMOD_ENTITYTRANSLATE:
10424                         // this is used in Q3 to allow the gamecode to control texcoord
10425                         // scrolling on the entity, which is not supported in darkplaces yet.
10426                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10427                         break;
10428                 case Q3TCMOD_ROTATE:
10429                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10430                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10431                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10432                         break;
10433                 case Q3TCMOD_SCALE:
10434                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10435                         break;
10436                 case Q3TCMOD_SCROLL:
10437                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10438                         break;
10439                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10440                         w = (int) tcmod->parms[0];
10441                         h = (int) tcmod->parms[1];
10442                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10443                         f = f - floor(f);
10444                         idx = (int) floor(f * w * h);
10445                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10446                         break;
10447                 case Q3TCMOD_STRETCH:
10448                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10449                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10450                         break;
10451                 case Q3TCMOD_TRANSFORM:
10452                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10453                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10454                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10455                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10456                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10457                         break;
10458                 case Q3TCMOD_TURBULENT:
10459                         // this is handled in the RSurf_PrepareVertices function
10460                         matrix = identitymatrix;
10461                         break;
10462         }
10463         temp = *texmatrix;
10464         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10465 }
10466
10467 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10468 {
10469         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10470         char name[MAX_QPATH];
10471         skinframe_t *skinframe;
10472         unsigned char pixels[296*194];
10473         strlcpy(cache->name, skinname, sizeof(cache->name));
10474         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10475         if (developer_loading.integer)
10476                 Con_Printf("loading %s\n", name);
10477         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10478         if (!skinframe || !skinframe->base)
10479         {
10480                 unsigned char *f;
10481                 fs_offset_t filesize;
10482                 skinframe = NULL;
10483                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10484                 if (f)
10485                 {
10486                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10487                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10488                         Mem_Free(f);
10489                 }
10490         }
10491         cache->skinframe = skinframe;
10492 }
10493
10494 texture_t *R_GetCurrentTexture(texture_t *t)
10495 {
10496         int i;
10497         const entity_render_t *ent = rsurface.entity;
10498         dp_model_t *model = ent->model;
10499         q3shaderinfo_layer_tcmod_t *tcmod;
10500
10501         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10502                 return t->currentframe;
10503         t->update_lastrenderframe = r_textureframe;
10504         t->update_lastrenderentity = (void *)ent;
10505
10506         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10507                 t->camera_entity = ent->entitynumber;
10508         else
10509                 t->camera_entity = 0;
10510
10511         // switch to an alternate material if this is a q1bsp animated material
10512         {
10513                 texture_t *texture = t;
10514                 int s = rsurface.ent_skinnum;
10515                 if ((unsigned int)s >= (unsigned int)model->numskins)
10516                         s = 0;
10517                 if (model->skinscenes)
10518                 {
10519                         if (model->skinscenes[s].framecount > 1)
10520                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10521                         else
10522                                 s = model->skinscenes[s].firstframe;
10523                 }
10524                 if (s > 0)
10525                         t = t + s * model->num_surfaces;
10526                 if (t->animated)
10527                 {
10528                         // use an alternate animation if the entity's frame is not 0,
10529                         // and only if the texture has an alternate animation
10530                         if (rsurface.ent_alttextures && t->anim_total[1])
10531                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10532                         else
10533                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10534                 }
10535                 texture->currentframe = t;
10536         }
10537
10538         // update currentskinframe to be a qw skin or animation frame
10539         if (rsurface.ent_qwskin >= 0)
10540         {
10541                 i = rsurface.ent_qwskin;
10542                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10543                 {
10544                         r_qwskincache_size = cl.maxclients;
10545                         if (r_qwskincache)
10546                                 Mem_Free(r_qwskincache);
10547                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10548                 }
10549                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10550                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10551                 t->currentskinframe = r_qwskincache[i].skinframe;
10552                 if (t->currentskinframe == NULL)
10553                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10554         }
10555         else if (t->numskinframes >= 2)
10556                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10557         if (t->backgroundnumskinframes >= 2)
10558                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10559
10560         t->currentmaterialflags = t->basematerialflags;
10561         t->currentalpha = rsurface.colormod[3];
10562         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10563                 t->currentalpha *= r_wateralpha.value;
10564         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10565                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10566         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10567                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10568         if (!(rsurface.ent_flags & RENDER_LIGHT))
10569                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10570         else if (FAKELIGHT_ENABLED)
10571         {
10572                         // no modellight if using fakelight for the map
10573         }
10574         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10575         {
10576                 // pick a model lighting mode
10577                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10578                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10579                 else
10580                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10581         }
10582         if (rsurface.ent_flags & RENDER_ADDITIVE)
10583                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10584         else if (t->currentalpha < 1)
10585                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10586         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10587                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10588         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10589                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10590         if (t->backgroundnumskinframes)
10591                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10592         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10593         {
10594                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10595                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10596         }
10597         else
10598                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10599         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10600                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10601
10602         // there is no tcmod
10603         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10604         {
10605                 t->currenttexmatrix = r_waterscrollmatrix;
10606                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10607         }
10608         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10609         {
10610                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10611                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10612         }
10613
10614         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10615                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10616         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10617                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10618
10619         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10620         if (t->currentskinframe->qpixels)
10621                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10622         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10623         if (!t->basetexture)
10624                 t->basetexture = r_texture_notexture;
10625         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10626         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10627         t->nmaptexture = t->currentskinframe->nmap;
10628         if (!t->nmaptexture)
10629                 t->nmaptexture = r_texture_blanknormalmap;
10630         t->glosstexture = r_texture_black;
10631         t->glowtexture = t->currentskinframe->glow;
10632         t->fogtexture = t->currentskinframe->fog;
10633         t->reflectmasktexture = t->currentskinframe->reflect;
10634         if (t->backgroundnumskinframes)
10635         {
10636                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10637                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10638                 t->backgroundglosstexture = r_texture_black;
10639                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10640                 if (!t->backgroundnmaptexture)
10641                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10642         }
10643         else
10644         {
10645                 t->backgroundbasetexture = r_texture_white;
10646                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10647                 t->backgroundglosstexture = r_texture_black;
10648                 t->backgroundglowtexture = NULL;
10649         }
10650         t->specularpower = r_shadow_glossexponent.value;
10651         // TODO: store reference values for these in the texture?
10652         t->specularscale = 0;
10653         if (r_shadow_gloss.integer > 0)
10654         {
10655                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10656                 {
10657                         if (r_shadow_glossintensity.value > 0)
10658                         {
10659                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10660                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10661                                 t->specularscale = r_shadow_glossintensity.value;
10662                         }
10663                 }
10664                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10665                 {
10666                         t->glosstexture = r_texture_white;
10667                         t->backgroundglosstexture = r_texture_white;
10668                         t->specularscale = r_shadow_gloss2intensity.value;
10669                         t->specularpower = r_shadow_gloss2exponent.value;
10670                 }
10671         }
10672         t->specularscale *= t->specularscalemod;
10673         t->specularpower *= t->specularpowermod;
10674
10675         // lightmaps mode looks bad with dlights using actual texturing, so turn
10676         // off the colormap and glossmap, but leave the normalmap on as it still
10677         // accurately represents the shading involved
10678         if (gl_lightmaps.integer)
10679         {
10680                 t->basetexture = r_texture_grey128;
10681                 t->pantstexture = r_texture_black;
10682                 t->shirttexture = r_texture_black;
10683                 t->nmaptexture = r_texture_blanknormalmap;
10684                 t->glosstexture = r_texture_black;
10685                 t->glowtexture = NULL;
10686                 t->fogtexture = NULL;
10687                 t->reflectmasktexture = NULL;
10688                 t->backgroundbasetexture = NULL;
10689                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10690                 t->backgroundglosstexture = r_texture_black;
10691                 t->backgroundglowtexture = NULL;
10692                 t->specularscale = 0;
10693                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10694         }
10695
10696         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10697         VectorClear(t->dlightcolor);
10698         t->currentnumlayers = 0;
10699         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10700         {
10701                 int blendfunc1, blendfunc2;
10702                 qboolean depthmask;
10703                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10704                 {
10705                         blendfunc1 = GL_SRC_ALPHA;
10706                         blendfunc2 = GL_ONE;
10707                 }
10708                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10709                 {
10710                         blendfunc1 = GL_SRC_ALPHA;
10711                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10712                 }
10713                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10714                 {
10715                         blendfunc1 = t->customblendfunc[0];
10716                         blendfunc2 = t->customblendfunc[1];
10717                 }
10718                 else
10719                 {
10720                         blendfunc1 = GL_ONE;
10721                         blendfunc2 = GL_ZERO;
10722                 }
10723                 // don't colormod evilblend textures
10724                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10725                         VectorSet(t->lightmapcolor, 1, 1, 1);
10726                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10727                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10728                 {
10729                         // fullbright is not affected by r_refdef.lightmapintensity
10730                         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]);
10731                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10732                                 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]);
10733                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10734                                 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]);
10735                 }
10736                 else
10737                 {
10738                         vec3_t ambientcolor;
10739                         float colorscale;
10740                         // set the color tint used for lights affecting this surface
10741                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10742                         colorscale = 2;
10743                         // q3bsp has no lightmap updates, so the lightstylevalue that
10744                         // would normally be baked into the lightmap must be
10745                         // applied to the color
10746                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10747                         if (model->type == mod_brushq3)
10748                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10749                         colorscale *= r_refdef.lightmapintensity;
10750                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10751                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10752                         // basic lit geometry
10753                         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]);
10754                         // add pants/shirt if needed
10755                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10756                                 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]);
10757                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10758                                 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]);
10759                         // now add ambient passes if needed
10760                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10761                         {
10762                                 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]);
10763                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10764                                         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]);
10765                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10766                                         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]);
10767                         }
10768                 }
10769                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10770                         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]);
10771                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10772                 {
10773                         // if this is opaque use alpha blend which will darken the earlier
10774                         // passes cheaply.
10775                         //
10776                         // if this is an alpha blended material, all the earlier passes
10777                         // were darkened by fog already, so we only need to add the fog
10778                         // color ontop through the fog mask texture
10779                         //
10780                         // if this is an additive blended material, all the earlier passes
10781                         // were darkened by fog already, and we should not add fog color
10782                         // (because the background was not darkened, there is no fog color
10783                         // that was lost behind it).
10784                         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]);
10785                 }
10786         }
10787
10788         return t->currentframe;
10789 }
10790
10791 rsurfacestate_t rsurface;
10792
10793 void R_Mesh_ResizeArrays(int newvertices)
10794 {
10795         unsigned char *base;
10796         size_t size;
10797         if (rsurface.array_size >= newvertices)
10798                 return;
10799         if (rsurface.array_base)
10800                 Mem_Free(rsurface.array_base);
10801         rsurface.array_size = (newvertices + 1023) & ~1023;
10802         size = 0;
10803         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10804         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10805         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10806         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10807         size += rsurface.array_size * sizeof(float[3]);
10808         size += rsurface.array_size * sizeof(float[3]);
10809         size += rsurface.array_size * sizeof(float[3]);
10810         size += rsurface.array_size * sizeof(float[3]);
10811         size += rsurface.array_size * sizeof(float[3]);
10812         size += rsurface.array_size * sizeof(float[3]);
10813         size += rsurface.array_size * sizeof(float[3]);
10814         size += rsurface.array_size * sizeof(float[3]);
10815         size += rsurface.array_size * sizeof(float[4]);
10816         size += rsurface.array_size * sizeof(float[2]);
10817         size += rsurface.array_size * sizeof(float[2]);
10818         size += rsurface.array_size * sizeof(float[4]);
10819         size += rsurface.array_size * sizeof(int[3]);
10820         size += rsurface.array_size * sizeof(unsigned short[3]);
10821         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10822         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10823         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10824         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10825         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10826         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10827         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10828         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10829         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10830         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10831         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10832         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10833         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10834         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10835         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10836         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10837         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10838         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
10839         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10840 }
10841
10842 void RSurf_ActiveWorldEntity(void)
10843 {
10844         dp_model_t *model = r_refdef.scene.worldmodel;
10845         //if (rsurface.entity == r_refdef.scene.worldentity)
10846         //      return;
10847         rsurface.entity = r_refdef.scene.worldentity;
10848         rsurface.skeleton = NULL;
10849         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10850         rsurface.ent_skinnum = 0;
10851         rsurface.ent_qwskin = -1;
10852         rsurface.ent_shadertime = 0;
10853         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10854         if (rsurface.array_size < model->surfmesh.num_vertices)
10855                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10856         rsurface.matrix = identitymatrix;
10857         rsurface.inversematrix = identitymatrix;
10858         rsurface.matrixscale = 1;
10859         rsurface.inversematrixscale = 1;
10860         R_EntityMatrix(&identitymatrix);
10861         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10862         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10863         rsurface.fograngerecip = r_refdef.fograngerecip;
10864         rsurface.fogheightfade = r_refdef.fogheightfade;
10865         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10866         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10867         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10868         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10869         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10870         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10871         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10872         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10873         rsurface.colormod[3] = 1;
10874         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);
10875         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10876         rsurface.frameblend[0].lerp = 1;
10877         rsurface.ent_alttextures = false;
10878         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10879         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10880         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10881         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10882         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10883         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10884         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10885         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10886         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10887         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10888         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10889         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10890         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10891         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10892         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10893         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10894         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10895         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10896         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10897         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10898         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10899         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10900         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10901         rsurface.modelelement3i = model->surfmesh.data_element3i;
10902         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10903         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10904         rsurface.modelelement3s = model->surfmesh.data_element3s;
10905         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10906         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10907         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10908         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10909         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10910         rsurface.modelsurfaces = model->data_surfaces;
10911         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10912         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10913         rsurface.modelvertexposition = model->surfmesh.vertexposition;
10914         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10915         rsurface.modelgeneratedvertex = false;
10916         rsurface.batchgeneratedvertex = false;
10917         rsurface.batchfirstvertex = 0;
10918         rsurface.batchnumvertices = 0;
10919         rsurface.batchfirsttriangle = 0;
10920         rsurface.batchnumtriangles = 0;
10921         rsurface.batchvertex3f  = NULL;
10922         rsurface.batchvertex3f_vertexbuffer = NULL;
10923         rsurface.batchvertex3f_bufferoffset = 0;
10924         rsurface.batchsvector3f = NULL;
10925         rsurface.batchsvector3f_vertexbuffer = NULL;
10926         rsurface.batchsvector3f_bufferoffset = 0;
10927         rsurface.batchtvector3f = NULL;
10928         rsurface.batchtvector3f_vertexbuffer = NULL;
10929         rsurface.batchtvector3f_bufferoffset = 0;
10930         rsurface.batchnormal3f  = NULL;
10931         rsurface.batchnormal3f_vertexbuffer = NULL;
10932         rsurface.batchnormal3f_bufferoffset = 0;
10933         rsurface.batchlightmapcolor4f = NULL;
10934         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10935         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10936         rsurface.batchtexcoordtexture2f = NULL;
10937         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10938         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10939         rsurface.batchtexcoordlightmap2f = NULL;
10940         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10941         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10942         rsurface.batchvertexmesh = NULL;
10943         rsurface.batchvertexmeshbuffer = NULL;
10944         rsurface.batchvertexposition = NULL;
10945         rsurface.batchvertexpositionbuffer = NULL;
10946         rsurface.batchelement3i = NULL;
10947         rsurface.batchelement3i_indexbuffer = NULL;
10948         rsurface.batchelement3i_bufferoffset = 0;
10949         rsurface.batchelement3s = NULL;
10950         rsurface.batchelement3s_indexbuffer = NULL;
10951         rsurface.batchelement3s_bufferoffset = 0;
10952         rsurface.passcolor4f = NULL;
10953         rsurface.passcolor4f_vertexbuffer = NULL;
10954         rsurface.passcolor4f_bufferoffset = 0;
10955 }
10956
10957 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10958 {
10959         dp_model_t *model = ent->model;
10960         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10961         //      return;
10962         rsurface.entity = (entity_render_t *)ent;
10963         rsurface.skeleton = ent->skeleton;
10964         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10965         rsurface.ent_skinnum = ent->skinnum;
10966         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;
10967         rsurface.ent_shadertime = ent->shadertime;
10968         rsurface.ent_flags = ent->flags;
10969         if (rsurface.array_size < model->surfmesh.num_vertices)
10970                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10971         rsurface.matrix = ent->matrix;
10972         rsurface.inversematrix = ent->inversematrix;
10973         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10974         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10975         R_EntityMatrix(&rsurface.matrix);
10976         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10977         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10978         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10979         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10980         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10981         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10982         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10983         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10984         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10985         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10986         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10987         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10988         rsurface.colormod[3] = ent->alpha;
10989         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10990         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10991         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10992         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10993         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10994         if (ent->model->brush.submodel && !prepass)
10995         {
10996                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10997                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10998         }
10999         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
11000         {
11001                 if (ent->animcache_vertex3f && !r_framedata_failed)
11002                 {
11003                         rsurface.modelvertex3f = ent->animcache_vertex3f;
11004                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
11005                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
11006                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
11007                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
11008                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
11009                         rsurface.modelvertexposition = ent->animcache_vertexposition;
11010                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
11011                 }
11012                 else if (wanttangents)
11013                 {
11014                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11015                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11016                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11017                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11018                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
11019                         rsurface.modelvertexmesh = NULL;
11020                         rsurface.modelvertexmeshbuffer = NULL;
11021                         rsurface.modelvertexposition = NULL;
11022                         rsurface.modelvertexpositionbuffer = NULL;
11023                 }
11024                 else if (wantnormals)
11025                 {
11026                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11027                         rsurface.modelsvector3f = NULL;
11028                         rsurface.modeltvector3f = NULL;
11029                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11030                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
11031                         rsurface.modelvertexmesh = NULL;
11032                         rsurface.modelvertexmeshbuffer = NULL;
11033                         rsurface.modelvertexposition = NULL;
11034                         rsurface.modelvertexpositionbuffer = NULL;
11035                 }
11036                 else
11037                 {
11038                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11039                         rsurface.modelsvector3f = NULL;
11040                         rsurface.modeltvector3f = NULL;
11041                         rsurface.modelnormal3f = NULL;
11042                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
11043                         rsurface.modelvertexmesh = NULL;
11044                         rsurface.modelvertexmeshbuffer = NULL;
11045                         rsurface.modelvertexposition = NULL;
11046                         rsurface.modelvertexpositionbuffer = NULL;
11047                 }
11048                 rsurface.modelvertex3f_vertexbuffer = 0;
11049                 rsurface.modelvertex3f_bufferoffset = 0;
11050                 rsurface.modelsvector3f_vertexbuffer = 0;
11051                 rsurface.modelsvector3f_bufferoffset = 0;
11052                 rsurface.modeltvector3f_vertexbuffer = 0;
11053                 rsurface.modeltvector3f_bufferoffset = 0;
11054                 rsurface.modelnormal3f_vertexbuffer = 0;
11055                 rsurface.modelnormal3f_bufferoffset = 0;
11056                 rsurface.modelgeneratedvertex = true;
11057         }
11058         else
11059         {
11060                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
11061                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11062                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11063                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11064                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11065                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11066                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11067                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11068                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11069                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
11070                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11071                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11072                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11073                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11074                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
11075                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
11076                 rsurface.modelgeneratedvertex = false;
11077         }
11078         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11079         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11080         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11081         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11082         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11083         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11084         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11085         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11086         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11087         rsurface.modelelement3i = model->surfmesh.data_element3i;
11088         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11089         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11090         rsurface.modelelement3s = model->surfmesh.data_element3s;
11091         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11092         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11093         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11094         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11095         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11096         rsurface.modelsurfaces = model->data_surfaces;
11097         rsurface.batchgeneratedvertex = false;
11098         rsurface.batchfirstvertex = 0;
11099         rsurface.batchnumvertices = 0;
11100         rsurface.batchfirsttriangle = 0;
11101         rsurface.batchnumtriangles = 0;
11102         rsurface.batchvertex3f  = NULL;
11103         rsurface.batchvertex3f_vertexbuffer = NULL;
11104         rsurface.batchvertex3f_bufferoffset = 0;
11105         rsurface.batchsvector3f = NULL;
11106         rsurface.batchsvector3f_vertexbuffer = NULL;
11107         rsurface.batchsvector3f_bufferoffset = 0;
11108         rsurface.batchtvector3f = NULL;
11109         rsurface.batchtvector3f_vertexbuffer = NULL;
11110         rsurface.batchtvector3f_bufferoffset = 0;
11111         rsurface.batchnormal3f  = NULL;
11112         rsurface.batchnormal3f_vertexbuffer = NULL;
11113         rsurface.batchnormal3f_bufferoffset = 0;
11114         rsurface.batchlightmapcolor4f = NULL;
11115         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11116         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11117         rsurface.batchtexcoordtexture2f = NULL;
11118         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11119         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11120         rsurface.batchtexcoordlightmap2f = NULL;
11121         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11122         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11123         rsurface.batchvertexmesh = NULL;
11124         rsurface.batchvertexmeshbuffer = NULL;
11125         rsurface.batchvertexposition = NULL;
11126         rsurface.batchvertexpositionbuffer = NULL;
11127         rsurface.batchelement3i = NULL;
11128         rsurface.batchelement3i_indexbuffer = NULL;
11129         rsurface.batchelement3i_bufferoffset = 0;
11130         rsurface.batchelement3s = NULL;
11131         rsurface.batchelement3s_indexbuffer = NULL;
11132         rsurface.batchelement3s_bufferoffset = 0;
11133         rsurface.passcolor4f = NULL;
11134         rsurface.passcolor4f_vertexbuffer = NULL;
11135         rsurface.passcolor4f_bufferoffset = 0;
11136 }
11137
11138 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)
11139 {
11140         int i;
11141
11142         rsurface.entity = r_refdef.scene.worldentity;
11143         rsurface.skeleton = NULL;
11144         rsurface.ent_skinnum = 0;
11145         rsurface.ent_qwskin = -1;
11146         rsurface.ent_shadertime = shadertime;
11147         rsurface.ent_flags = entflags;
11148         rsurface.modelnumvertices = numvertices;
11149         rsurface.modelnumtriangles = numtriangles;
11150         if (rsurface.array_size < rsurface.modelnumvertices)
11151                 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
11152         rsurface.matrix = *matrix;
11153         rsurface.inversematrix = *inversematrix;
11154         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11155         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11156         R_EntityMatrix(&rsurface.matrix);
11157         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11158         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11159         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11160         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11161         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11162         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11163         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11164         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11165         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11166         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11167         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11168         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11169         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);
11170         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11171         rsurface.frameblend[0].lerp = 1;
11172         rsurface.ent_alttextures = false;
11173         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11174         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11175         if (wanttangents)
11176         {
11177                 rsurface.modelvertex3f = vertex3f;
11178                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
11179                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
11180                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11181         }
11182         else if (wantnormals)
11183         {
11184                 rsurface.modelvertex3f = vertex3f;
11185                 rsurface.modelsvector3f = NULL;
11186                 rsurface.modeltvector3f = NULL;
11187                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11188         }
11189         else
11190         {
11191                 rsurface.modelvertex3f = vertex3f;
11192                 rsurface.modelsvector3f = NULL;
11193                 rsurface.modeltvector3f = NULL;
11194                 rsurface.modelnormal3f = NULL;
11195         }
11196         rsurface.modelvertexmesh = NULL;
11197         rsurface.modelvertexmeshbuffer = NULL;
11198         rsurface.modelvertexposition = NULL;
11199         rsurface.modelvertexpositionbuffer = NULL;
11200         rsurface.modelvertex3f_vertexbuffer = 0;
11201         rsurface.modelvertex3f_bufferoffset = 0;
11202         rsurface.modelsvector3f_vertexbuffer = 0;
11203         rsurface.modelsvector3f_bufferoffset = 0;
11204         rsurface.modeltvector3f_vertexbuffer = 0;
11205         rsurface.modeltvector3f_bufferoffset = 0;
11206         rsurface.modelnormal3f_vertexbuffer = 0;
11207         rsurface.modelnormal3f_bufferoffset = 0;
11208         rsurface.modelgeneratedvertex = true;
11209         rsurface.modellightmapcolor4f  = color4f;
11210         rsurface.modellightmapcolor4f_vertexbuffer = 0;
11211         rsurface.modellightmapcolor4f_bufferoffset = 0;
11212         rsurface.modeltexcoordtexture2f  = texcoord2f;
11213         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11214         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11215         rsurface.modeltexcoordlightmap2f  = NULL;
11216         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11217         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11218         rsurface.modelelement3i = element3i;
11219         rsurface.modelelement3i_indexbuffer = NULL;
11220         rsurface.modelelement3i_bufferoffset = 0;
11221         rsurface.modelelement3s = element3s;
11222         rsurface.modelelement3s_indexbuffer = NULL;
11223         rsurface.modelelement3s_bufferoffset = 0;
11224         rsurface.modellightmapoffsets = NULL;
11225         rsurface.modelsurfaces = NULL;
11226         rsurface.batchgeneratedvertex = false;
11227         rsurface.batchfirstvertex = 0;
11228         rsurface.batchnumvertices = 0;
11229         rsurface.batchfirsttriangle = 0;
11230         rsurface.batchnumtriangles = 0;
11231         rsurface.batchvertex3f  = NULL;
11232         rsurface.batchvertex3f_vertexbuffer = NULL;
11233         rsurface.batchvertex3f_bufferoffset = 0;
11234         rsurface.batchsvector3f = NULL;
11235         rsurface.batchsvector3f_vertexbuffer = NULL;
11236         rsurface.batchsvector3f_bufferoffset = 0;
11237         rsurface.batchtvector3f = NULL;
11238         rsurface.batchtvector3f_vertexbuffer = NULL;
11239         rsurface.batchtvector3f_bufferoffset = 0;
11240         rsurface.batchnormal3f  = NULL;
11241         rsurface.batchnormal3f_vertexbuffer = NULL;
11242         rsurface.batchnormal3f_bufferoffset = 0;
11243         rsurface.batchlightmapcolor4f = NULL;
11244         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11245         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11246         rsurface.batchtexcoordtexture2f = NULL;
11247         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11248         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11249         rsurface.batchtexcoordlightmap2f = NULL;
11250         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11251         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11252         rsurface.batchvertexmesh = NULL;
11253         rsurface.batchvertexmeshbuffer = NULL;
11254         rsurface.batchvertexposition = NULL;
11255         rsurface.batchvertexpositionbuffer = NULL;
11256         rsurface.batchelement3i = NULL;
11257         rsurface.batchelement3i_indexbuffer = NULL;
11258         rsurface.batchelement3i_bufferoffset = 0;
11259         rsurface.batchelement3s = NULL;
11260         rsurface.batchelement3s_indexbuffer = NULL;
11261         rsurface.batchelement3s_bufferoffset = 0;
11262         rsurface.passcolor4f = NULL;
11263         rsurface.passcolor4f_vertexbuffer = NULL;
11264         rsurface.passcolor4f_bufferoffset = 0;
11265
11266         if (rsurface.modelnumvertices && rsurface.modelelement3i)
11267         {
11268                 if ((wantnormals || wanttangents) && !normal3f)
11269                 {
11270                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11271                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11272                 }
11273                 if (wanttangents && !svector3f)
11274                 {
11275                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
11276                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11277                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11278                 }
11279         }
11280
11281         // now convert arrays into vertexmesh structs
11282         for (i = 0;i < numvertices;i++)
11283         {
11284                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
11285                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
11286                 if (rsurface.modelsvector3f)
11287                         VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
11288                 if (rsurface.modeltvector3f)
11289                         VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
11290                 if (rsurface.modelnormal3f)
11291                         VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
11292                 if (rsurface.modellightmapcolor4f)
11293                         Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
11294                 if (rsurface.modeltexcoordtexture2f)
11295                         Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
11296                 if (rsurface.modeltexcoordlightmap2f)
11297                         Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
11298         }
11299 }
11300
11301 float RSurf_FogPoint(const float *v)
11302 {
11303         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11304         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11305         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11306         float FogHeightFade = r_refdef.fogheightfade;
11307         float fogfrac;
11308         unsigned int fogmasktableindex;
11309         if (r_refdef.fogplaneviewabove)
11310                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11311         else
11312                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11313         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11314         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11315 }
11316
11317 float RSurf_FogVertex(const float *v)
11318 {
11319         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11320         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11321         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11322         float FogHeightFade = rsurface.fogheightfade;
11323         float fogfrac;
11324         unsigned int fogmasktableindex;
11325         if (r_refdef.fogplaneviewabove)
11326                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11327         else
11328                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11329         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11330         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11331 }
11332
11333 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11334 {
11335         int i;
11336         for (i = 0;i < numelements;i++)
11337                 outelement3i[i] = inelement3i[i] + adjust;
11338 }
11339
11340 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11341 extern cvar_t gl_vbo;
11342 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11343 {
11344         int deformindex;
11345         int firsttriangle;
11346         int numtriangles;
11347         int firstvertex;
11348         int endvertex;
11349         int numvertices;
11350         int surfacefirsttriangle;
11351         int surfacenumtriangles;
11352         int surfacefirstvertex;
11353         int surfaceendvertex;
11354         int surfacenumvertices;
11355         int needsupdate;
11356         int i, j;
11357         qboolean gaps;
11358         qboolean dynamicvertex;
11359         float amplitude;
11360         float animpos;
11361         float scale;
11362         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11363         float waveparms[4];
11364         q3shaderinfo_deform_t *deform;
11365         const msurface_t *surface, *firstsurface;
11366         r_vertexposition_t *vertexposition;
11367         r_vertexmesh_t *vertexmesh;
11368         if (!texturenumsurfaces)
11369                 return;
11370         // find vertex range of this surface batch
11371         gaps = false;
11372         firstsurface = texturesurfacelist[0];
11373         firsttriangle = firstsurface->num_firsttriangle;
11374         numtriangles = 0;
11375         firstvertex = endvertex = firstsurface->num_firstvertex;
11376         for (i = 0;i < texturenumsurfaces;i++)
11377         {
11378                 surface = texturesurfacelist[i];
11379                 if (surface != firstsurface + i)
11380                         gaps = true;
11381                 surfacefirstvertex = surface->num_firstvertex;
11382                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11383                 surfacenumtriangles = surface->num_triangles;
11384                 if (firstvertex > surfacefirstvertex)
11385                         firstvertex = surfacefirstvertex;
11386                 if (endvertex < surfaceendvertex)
11387                         endvertex = surfaceendvertex;
11388                 numtriangles += surfacenumtriangles;
11389         }
11390         if (!numtriangles)
11391                 return;
11392
11393         // we now know the vertex range used, and if there are any gaps in it
11394         rsurface.batchfirstvertex = firstvertex;
11395         rsurface.batchnumvertices = endvertex - firstvertex;
11396         rsurface.batchfirsttriangle = firsttriangle;
11397         rsurface.batchnumtriangles = numtriangles;
11398
11399         // this variable holds flags for which properties have been updated that
11400         // may require regenerating vertexmesh or vertexposition arrays...
11401         needsupdate = 0;
11402
11403         // check if any dynamic vertex processing must occur
11404         dynamicvertex = false;
11405
11406         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11407                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11408         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11409         {
11410                 switch (deform->deform)
11411                 {
11412                 default:
11413                 case Q3DEFORM_PROJECTIONSHADOW:
11414                 case Q3DEFORM_TEXT0:
11415                 case Q3DEFORM_TEXT1:
11416                 case Q3DEFORM_TEXT2:
11417                 case Q3DEFORM_TEXT3:
11418                 case Q3DEFORM_TEXT4:
11419                 case Q3DEFORM_TEXT5:
11420                 case Q3DEFORM_TEXT6:
11421                 case Q3DEFORM_TEXT7:
11422                 case Q3DEFORM_NONE:
11423                         break;
11424                 case Q3DEFORM_AUTOSPRITE:
11425                         dynamicvertex = true;
11426                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11427                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11428                         break;
11429                 case Q3DEFORM_AUTOSPRITE2:
11430                         dynamicvertex = true;
11431                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11432                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11433                         break;
11434                 case Q3DEFORM_NORMAL:
11435                         dynamicvertex = true;
11436                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11437                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11438                         break;
11439                 case Q3DEFORM_WAVE:
11440                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11441                                 break; // if wavefunc is a nop, ignore this transform
11442                         dynamicvertex = true;
11443                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11444                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11445                         break;
11446                 case Q3DEFORM_BULGE:
11447                         dynamicvertex = true;
11448                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11449                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11450                         break;
11451                 case Q3DEFORM_MOVE:
11452                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11453                                 break; // if wavefunc is a nop, ignore this transform
11454                         dynamicvertex = true;
11455                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11456                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11457                         break;
11458                 }
11459         }
11460         switch(rsurface.texture->tcgen.tcgen)
11461         {
11462         default:
11463         case Q3TCGEN_TEXTURE:
11464                 break;
11465         case Q3TCGEN_LIGHTMAP:
11466                 dynamicvertex = true;
11467                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11468                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11469                 break;
11470         case Q3TCGEN_VECTOR:
11471                 dynamicvertex = true;
11472                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11473                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11474                 break;
11475         case Q3TCGEN_ENVIRONMENT:
11476                 dynamicvertex = true;
11477                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11478                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11479                 break;
11480         }
11481         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11482         {
11483                 dynamicvertex = true;
11484                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11485                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11486         }
11487
11488         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11489         {
11490                 dynamicvertex = true;
11491                 batchneed |= BATCHNEED_NOGAPS;
11492                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11493         }
11494
11495         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11496         {
11497                 dynamicvertex = true;
11498                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11499                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11500         }
11501
11502         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11503         {
11504                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11505                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11506                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11507                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11508                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11509                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11510                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11511         }
11512
11513         // when the model data has no vertex buffer (dynamic mesh), we need to
11514         // eliminate gaps
11515         if (!rsurface.modelvertexmeshbuffer)
11516                 batchneed |= BATCHNEED_NOGAPS;
11517
11518         // if needsupdate, we have to do a dynamic vertex batch for sure
11519         if (needsupdate & batchneed)
11520                 dynamicvertex = true;
11521
11522         // see if we need to build vertexmesh from arrays
11523         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11524                 dynamicvertex = true;
11525
11526         // see if we need to build vertexposition from arrays
11527         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11528                 dynamicvertex = true;
11529
11530         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11531         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11532                 dynamicvertex = true;
11533
11534         // if there is a chance of animated vertex colors, it's a dynamic batch
11535         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11536                 dynamicvertex = true;
11537
11538         rsurface.batchvertex3f = rsurface.modelvertex3f;
11539         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11540         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11541         rsurface.batchsvector3f = rsurface.modelsvector3f;
11542         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11543         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11544         rsurface.batchtvector3f = rsurface.modeltvector3f;
11545         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11546         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11547         rsurface.batchnormal3f = rsurface.modelnormal3f;
11548         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11549         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11550         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11551         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11552         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11553         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11554         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11555         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11556         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11557         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11558         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11559         rsurface.batchvertexposition = rsurface.modelvertexposition;
11560         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11561         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11562         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11563         rsurface.batchelement3i = rsurface.modelelement3i;
11564         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11565         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11566         rsurface.batchelement3s = rsurface.modelelement3s;
11567         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11568         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11569
11570         // if any dynamic vertex processing has to occur in software, we copy the
11571         // entire surface list together before processing to rebase the vertices
11572         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11573         //
11574         // if any gaps exist and we do not have a static vertex buffer, we have to
11575         // copy the surface list together to avoid wasting upload bandwidth on the
11576         // vertices in the gaps.
11577         //
11578         // if gaps exist and we have a static vertex buffer, we still have to
11579         // combine the index buffer ranges into one dynamic index buffer.
11580         //
11581         // in all cases we end up with data that can be drawn in one call.
11582
11583         if (!dynamicvertex)
11584         {
11585                 // static vertex data, just set pointers...
11586                 rsurface.batchgeneratedvertex = false;
11587                 // if there are gaps, we want to build a combined index buffer,
11588                 // otherwise use the original static buffer with an appropriate offset
11589                 if (gaps)
11590                 {
11591                         firsttriangle = 0;
11592                         numtriangles = 0;
11593                         for (i = 0;i < texturenumsurfaces;i++)
11594                         {
11595                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11596                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11597                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11598                                 numtriangles += surfacenumtriangles;
11599                         }
11600                         rsurface.batchelement3i = rsurface.array_batchelement3i;
11601                         rsurface.batchelement3i_indexbuffer = NULL;
11602                         rsurface.batchelement3i_bufferoffset = 0;
11603                         rsurface.batchelement3s = NULL;
11604                         rsurface.batchelement3s_indexbuffer = NULL;
11605                         rsurface.batchelement3s_bufferoffset = 0;
11606                         if (endvertex <= 65536)
11607                         {
11608                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
11609                                 for (i = 0;i < numtriangles*3;i++)
11610                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11611                         }
11612                         rsurface.batchfirsttriangle = firsttriangle;
11613                         rsurface.batchnumtriangles = numtriangles;
11614                 }
11615                 return;
11616         }
11617
11618         // something needs software processing, do it for real...
11619         // we only directly handle interleaved array data in this case...
11620         rsurface.batchgeneratedvertex = true;
11621
11622         // now copy the vertex data into a combined array and make an index array
11623         // (this is what Quake3 does all the time)
11624         //if (gaps || rsurface.batchfirstvertex)
11625         {
11626                 rsurface.batchvertexposition = NULL;
11627                 rsurface.batchvertexpositionbuffer = NULL;
11628                 rsurface.batchvertexmesh = NULL;
11629                 rsurface.batchvertexmeshbuffer = NULL;
11630                 rsurface.batchvertex3f = NULL;
11631                 rsurface.batchvertex3f_vertexbuffer = NULL;
11632                 rsurface.batchvertex3f_bufferoffset = 0;
11633                 rsurface.batchsvector3f = NULL;
11634                 rsurface.batchsvector3f_vertexbuffer = NULL;
11635                 rsurface.batchsvector3f_bufferoffset = 0;
11636                 rsurface.batchtvector3f = NULL;
11637                 rsurface.batchtvector3f_vertexbuffer = NULL;
11638                 rsurface.batchtvector3f_bufferoffset = 0;
11639                 rsurface.batchnormal3f = NULL;
11640                 rsurface.batchnormal3f_vertexbuffer = NULL;
11641                 rsurface.batchnormal3f_bufferoffset = 0;
11642                 rsurface.batchlightmapcolor4f = NULL;
11643                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11644                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11645                 rsurface.batchtexcoordtexture2f = NULL;
11646                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11647                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11648                 rsurface.batchtexcoordlightmap2f = NULL;
11649                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11650                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11651                 rsurface.batchelement3i = rsurface.array_batchelement3i;
11652                 rsurface.batchelement3i_indexbuffer = NULL;
11653                 rsurface.batchelement3i_bufferoffset = 0;
11654                 rsurface.batchelement3s = NULL;
11655                 rsurface.batchelement3s_indexbuffer = NULL;
11656                 rsurface.batchelement3s_bufferoffset = 0;
11657                 // we'll only be setting up certain arrays as needed
11658                 if (batchneed & BATCHNEED_VERTEXPOSITION)
11659                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11660                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11661                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11662                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11663                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11664                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11665                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11666                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11667                 {
11668                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11669                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11670                 }
11671                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11672                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11673                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11674                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11675                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11676                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11677                 numvertices = 0;
11678                 numtriangles = 0;
11679                 for (i = 0;i < texturenumsurfaces;i++)
11680                 {
11681                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11682                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11683                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11684                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11685                         // copy only the data requested
11686                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11687                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11688                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11689                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11690                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11691                         {
11692                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11693                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11694                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11695                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11696                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11697                                 {
11698                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11699                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11700                                 }
11701                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11702                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11703                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11704                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11705                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11706                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11707                         }
11708                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11709                         numvertices += surfacenumvertices;
11710                         numtriangles += surfacenumtriangles;
11711                 }
11712
11713                 // generate a 16bit index array as well if possible
11714                 // (in general, dynamic batches fit)
11715                 if (numvertices <= 65536)
11716                 {
11717                         rsurface.batchelement3s = rsurface.array_batchelement3s;
11718                         for (i = 0;i < numtriangles*3;i++)
11719                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11720                 }
11721
11722                 // since we've copied everything, the batch now starts at 0
11723                 rsurface.batchfirstvertex = 0;
11724                 rsurface.batchnumvertices = numvertices;
11725                 rsurface.batchfirsttriangle = 0;
11726                 rsurface.batchnumtriangles = numtriangles;
11727         }
11728
11729         // q1bsp surfaces rendered in vertex color mode have to have colors
11730         // calculated based on lightstyles
11731         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11732         {
11733                 // generate color arrays for the surfaces in this list
11734                 int c[4];
11735                 int scale;
11736                 int size3;
11737                 const int *offsets;
11738                 const unsigned char *lm;
11739                 numvertices = 0;
11740                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11741                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11742                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11743                 for (i = 0;i < texturenumsurfaces;i++)
11744                 {
11745                         surface = texturesurfacelist[i];
11746                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11747                         surfacenumvertices = surface->num_vertices;
11748                         if (surface->lightmapinfo->samples)
11749                         {
11750                                 for (j = 0;j < surfacenumvertices;j++)
11751                                 {
11752                                         lm = surface->lightmapinfo->samples + offsets[j];
11753                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11754                                         VectorScale(lm, scale, c);
11755                                         if (surface->lightmapinfo->styles[1] != 255)
11756                                         {
11757                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11758                                                 lm += size3;
11759                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11760                                                 VectorMA(c, scale, lm, c);
11761                                                 if (surface->lightmapinfo->styles[2] != 255)
11762                                                 {
11763                                                         lm += size3;
11764                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11765                                                         VectorMA(c, scale, lm, c);
11766                                                         if (surface->lightmapinfo->styles[3] != 255)
11767                                                         {
11768                                                                 lm += size3;
11769                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11770                                                                 VectorMA(c, scale, lm, c);
11771                                                         }
11772                                                 }
11773                                         }
11774                                         c[0] >>= 15;
11775                                         c[1] >>= 15;
11776                                         c[2] >>= 15;
11777                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, min(c[0], 255) * (1.0f / 255.0f), min(c[1], 255) * (1.0f / 255.0f), min(c[2], 255) * (1.0f / 255.0f), 1);
11778                                         numvertices++;
11779                                 }
11780                         }
11781                         else
11782                         {
11783                                 for (j = 0;j < surfacenumvertices;j++)
11784                                 {
11785                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11786                                         numvertices++;
11787                                 }
11788                         }
11789                 }
11790         }
11791
11792         // if vertices are deformed (sprite flares and things in maps, possibly
11793         // water waves, bulges and other deformations), modify the copied vertices
11794         // in place
11795         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11796         {
11797                 switch (deform->deform)
11798                 {
11799                 default:
11800                 case Q3DEFORM_PROJECTIONSHADOW:
11801                 case Q3DEFORM_TEXT0:
11802                 case Q3DEFORM_TEXT1:
11803                 case Q3DEFORM_TEXT2:
11804                 case Q3DEFORM_TEXT3:
11805                 case Q3DEFORM_TEXT4:
11806                 case Q3DEFORM_TEXT5:
11807                 case Q3DEFORM_TEXT6:
11808                 case Q3DEFORM_TEXT7:
11809                 case Q3DEFORM_NONE:
11810                         break;
11811                 case Q3DEFORM_AUTOSPRITE:
11812                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11813                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11814                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11815                         VectorNormalize(newforward);
11816                         VectorNormalize(newright);
11817                         VectorNormalize(newup);
11818                         // a single autosprite surface can contain multiple sprites...
11819                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11820                         {
11821                                 VectorClear(center);
11822                                 for (i = 0;i < 4;i++)
11823                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11824                                 VectorScale(center, 0.25f, center);
11825                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11826                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11827                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11828                                 for (i = 0;i < 4;i++)
11829                                 {
11830                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11831                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11832                                 }
11833                         }
11834                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11835                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11836                         Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
11837                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11838                         rsurface.batchvertex3f_vertexbuffer = NULL;
11839                         rsurface.batchvertex3f_bufferoffset = 0;
11840                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11841                         rsurface.batchsvector3f_vertexbuffer = NULL;
11842                         rsurface.batchsvector3f_bufferoffset = 0;
11843                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11844                         rsurface.batchtvector3f_vertexbuffer = NULL;
11845                         rsurface.batchtvector3f_bufferoffset = 0;
11846                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11847                         rsurface.batchnormal3f_vertexbuffer = NULL;
11848                         rsurface.batchnormal3f_bufferoffset = 0;
11849                         break;
11850                 case Q3DEFORM_AUTOSPRITE2:
11851                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11852                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11853                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11854                         VectorNormalize(newforward);
11855                         VectorNormalize(newright);
11856                         VectorNormalize(newup);
11857                         {
11858                                 const float *v1, *v2;
11859                                 vec3_t start, end;
11860                                 float f, l;
11861                                 struct
11862                                 {
11863                                         float length2;
11864                                         const float *v1;
11865                                         const float *v2;
11866                                 }
11867                                 shortest[2];
11868                                 memset(shortest, 0, sizeof(shortest));
11869                                 // a single autosprite surface can contain multiple sprites...
11870                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11871                                 {
11872                                         VectorClear(center);
11873                                         for (i = 0;i < 4;i++)
11874                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11875                                         VectorScale(center, 0.25f, center);
11876                                         // find the two shortest edges, then use them to define the
11877                                         // axis vectors for rotating around the central axis
11878                                         for (i = 0;i < 6;i++)
11879                                         {
11880                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11881                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11882                                                 l = VectorDistance2(v1, v2);
11883                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11884                                                 if (v1[2] != v2[2])
11885                                                         l += (1.0f / 1024.0f);
11886                                                 if (shortest[0].length2 > l || i == 0)
11887                                                 {
11888                                                         shortest[1] = shortest[0];
11889                                                         shortest[0].length2 = l;
11890                                                         shortest[0].v1 = v1;
11891                                                         shortest[0].v2 = v2;
11892                                                 }
11893                                                 else if (shortest[1].length2 > l || i == 1)
11894                                                 {
11895                                                         shortest[1].length2 = l;
11896                                                         shortest[1].v1 = v1;
11897                                                         shortest[1].v2 = v2;
11898                                                 }
11899                                         }
11900                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11901                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11902                                         // this calculates the right vector from the shortest edge
11903                                         // and the up vector from the edge midpoints
11904                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11905                                         VectorNormalize(right);
11906                                         VectorSubtract(end, start, up);
11907                                         VectorNormalize(up);
11908                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11909                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11910                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11911                                         VectorNegate(forward, forward);
11912                                         VectorReflect(forward, 0, up, forward);
11913                                         VectorNormalize(forward);
11914                                         CrossProduct(up, forward, newright);
11915                                         VectorNormalize(newright);
11916                                         // rotate the quad around the up axis vector, this is made
11917                                         // especially easy by the fact we know the quad is flat,
11918                                         // so we only have to subtract the center position and
11919                                         // measure distance along the right vector, and then
11920                                         // multiply that by the newright vector and add back the
11921                                         // center position
11922                                         // we also need to subtract the old position to undo the
11923                                         // displacement from the center, which we do with a
11924                                         // DotProduct, the subtraction/addition of center is also
11925                                         // optimized into DotProducts here
11926                                         l = DotProduct(right, center);
11927                                         for (i = 0;i < 4;i++)
11928                                         {
11929                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11930                                                 f = DotProduct(right, v1) - l;
11931                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11932                                         }
11933                                 }
11934                         }
11935                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11936                         rsurface.batchvertex3f_vertexbuffer = NULL;
11937                         rsurface.batchvertex3f_bufferoffset = 0;
11938                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11939                         {
11940                                 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11941                                 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11942                                 rsurface.batchnormal3f_vertexbuffer = NULL;
11943                                 rsurface.batchnormal3f_bufferoffset = 0;
11944                         }
11945                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11946                         {
11947                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
11948                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11949                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11950                                 rsurface.batchsvector3f_bufferoffset = 0;
11951                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11952                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11953                                 rsurface.batchtvector3f_bufferoffset = 0;
11954                         }
11955                         break;
11956                 case Q3DEFORM_NORMAL:
11957                         // deform the normals to make reflections wavey
11958                         for (j = 0;j < rsurface.batchnumvertices;j++)
11959                         {
11960                                 float vertex[3];
11961                                 float *normal = rsurface.array_batchnormal3f + 3*j;
11962                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11963                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11964                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11965                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11966                                 VectorNormalize(normal);
11967                         }
11968                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11969                         rsurface.batchnormal3f_vertexbuffer = NULL;
11970                         rsurface.batchnormal3f_bufferoffset = 0;
11971                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11972                         {
11973                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
11974                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11975                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11976                                 rsurface.batchsvector3f_bufferoffset = 0;
11977                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11978                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11979                                 rsurface.batchtvector3f_bufferoffset = 0;
11980                         }
11981                         break;
11982                 case Q3DEFORM_WAVE:
11983                         // deform vertex array to make wavey water and flags and such
11984                         waveparms[0] = deform->waveparms[0];
11985                         waveparms[1] = deform->waveparms[1];
11986                         waveparms[2] = deform->waveparms[2];
11987                         waveparms[3] = deform->waveparms[3];
11988                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11989                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11990                         // this is how a divisor of vertex influence on deformation
11991                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11992                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11993                         for (j = 0;j < rsurface.batchnumvertices;j++)
11994                         {
11995                                 // if the wavefunc depends on time, evaluate it per-vertex
11996                                 if (waveparms[3])
11997                                 {
11998                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11999                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12000                                 }
12001                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
12002                         }
12003                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12004                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
12005                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12006                         rsurface.batchvertex3f_vertexbuffer = NULL;
12007                         rsurface.batchvertex3f_bufferoffset = 0;
12008                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12009                         rsurface.batchnormal3f_vertexbuffer = NULL;
12010                         rsurface.batchnormal3f_bufferoffset = 0;
12011                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12012                         {
12013                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
12014                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12015                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12016                                 rsurface.batchsvector3f_bufferoffset = 0;
12017                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12018                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12019                                 rsurface.batchtvector3f_bufferoffset = 0;
12020                         }
12021                         break;
12022                 case Q3DEFORM_BULGE:
12023                         // deform vertex array to make the surface have moving bulges
12024                         for (j = 0;j < rsurface.batchnumvertices;j++)
12025                         {
12026                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
12027                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
12028                         }
12029                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12030                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
12031                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12032                         rsurface.batchvertex3f_vertexbuffer = NULL;
12033                         rsurface.batchvertex3f_bufferoffset = 0;
12034                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12035                         rsurface.batchnormal3f_vertexbuffer = NULL;
12036                         rsurface.batchnormal3f_bufferoffset = 0;
12037                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12038                         {
12039                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
12040                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12041                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12042                                 rsurface.batchsvector3f_bufferoffset = 0;
12043                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12044                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12045                                 rsurface.batchtvector3f_bufferoffset = 0;
12046                         }
12047                         break;
12048                 case Q3DEFORM_MOVE:
12049                         // deform vertex array
12050                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12051                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12052                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
12053                         VectorScale(deform->parms, scale, waveparms);
12054                         for (j = 0;j < rsurface.batchnumvertices;j++)
12055                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
12056                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12057                         rsurface.batchvertex3f_vertexbuffer = NULL;
12058                         rsurface.batchvertex3f_bufferoffset = 0;
12059                         break;
12060                 }
12061         }
12062
12063         // generate texcoords based on the chosen texcoord source
12064         switch(rsurface.texture->tcgen.tcgen)
12065         {
12066         default:
12067         case Q3TCGEN_TEXTURE:
12068                 break;
12069         case Q3TCGEN_LIGHTMAP:
12070                 if (rsurface.batchtexcoordlightmap2f)
12071                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
12072                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12073                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12074                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12075                 break;
12076         case Q3TCGEN_VECTOR:
12077                 for (j = 0;j < rsurface.batchnumvertices;j++)
12078                 {
12079                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12080                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12081                 }
12082                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12083                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12084                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12085                 break;
12086         case Q3TCGEN_ENVIRONMENT:
12087                 // make environment reflections using a spheremap
12088                 for (j = 0;j < rsurface.batchnumvertices;j++)
12089                 {
12090                         // identical to Q3A's method, but executed in worldspace so
12091                         // carried models can be shiny too
12092
12093                         float viewer[3], d, reflected[3], worldreflected[3];
12094
12095                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12096                         // VectorNormalize(viewer);
12097
12098                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12099
12100                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12101                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12102                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12103                         // note: this is proportinal to viewer, so we can normalize later
12104
12105                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12106                         VectorNormalize(worldreflected);
12107
12108                         // note: this sphere map only uses world x and z!
12109                         // so positive and negative y will LOOK THE SAME.
12110                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12111                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12112                 }
12113                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12114                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12115                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12116                 break;
12117         }
12118         // the only tcmod that needs software vertex processing is turbulent, so
12119         // check for it here and apply the changes if needed
12120         // and we only support that as the first one
12121         // (handling a mixture of turbulent and other tcmods would be problematic
12122         //  without punting it entirely to a software path)
12123         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12124         {
12125                 amplitude = rsurface.texture->tcmods[0].parms[1];
12126                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12127                 for (j = 0;j < rsurface.batchnumvertices;j++)
12128                 {
12129                         rsurface.array_batchtexcoordtexture2f[j*2+0] += amplitude * sin(((rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12130                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12131                 }
12132                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12133                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12134                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12135         }
12136
12137         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12138         {
12139                 // convert the modified arrays to vertex structs
12140                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
12141                 rsurface.batchvertexmeshbuffer = NULL;
12142                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12143                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12144                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12145                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12146                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12147                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12148                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12149                 {
12150                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12151                         {
12152                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12153                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12154                         }
12155                 }
12156                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12157                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12158                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12159                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12160                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12161                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12162                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12163                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12164                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12165         }
12166
12167         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
12168         {
12169                 // convert the modified arrays to vertex structs
12170                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
12171                 rsurface.batchvertexpositionbuffer = NULL;
12172                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
12173                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
12174                 else
12175                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
12176                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
12177         }
12178 }
12179
12180 void RSurf_DrawBatch(void)
12181 {
12182         R_Mesh_Draw(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchfirsttriangle, rsurface.batchnumtriangles, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
12183 }
12184
12185 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12186 {
12187         // pick the closest matching water plane
12188         int planeindex, vertexindex, bestplaneindex = -1;
12189         float d, bestd;
12190         vec3_t vert;
12191         const float *v;
12192         r_waterstate_waterplane_t *p;
12193         bestd = 0;
12194         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12195         {
12196                 if(p->camera_entity != rsurface.texture->camera_entity)
12197                         continue;
12198                 d = 0;
12199                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
12200                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12201                 {
12202                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
12203                         d += fabs(PlaneDiff(vert, &p->plane));
12204                 }
12205                 if (bestd > d || bestplaneindex < 0)
12206                 {
12207                         bestd = d;
12208                         bestplaneindex = planeindex;
12209                 }
12210         }
12211         return bestplaneindex;
12212 }
12213
12214 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12215 {
12216         int i;
12217         for (i = 0;i < rsurface.batchnumvertices;i++)
12218                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12219         rsurface.passcolor4f = rsurface.array_passcolor4f;
12220         rsurface.passcolor4f_vertexbuffer = 0;
12221         rsurface.passcolor4f_bufferoffset = 0;
12222 }
12223
12224 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12225 {
12226         int i;
12227         float f;
12228         const float *v;
12229         const float *c;
12230         float *c2;
12231         if (rsurface.passcolor4f)
12232         {
12233                 // generate color arrays
12234                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
12235                 {
12236                         f = RSurf_FogVertex(v);
12237                         c2[0] = c[0] * f;
12238                         c2[1] = c[1] * f;
12239                         c2[2] = c[2] * f;
12240                         c2[3] = c[3];
12241                 }
12242         }
12243         else
12244         {
12245                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12246                 {
12247                         f = RSurf_FogVertex(v);
12248                         c2[0] = f;
12249                         c2[1] = f;
12250                         c2[2] = f;
12251                         c2[3] = 1;
12252                 }
12253         }
12254         rsurface.passcolor4f = rsurface.array_passcolor4f;
12255         rsurface.passcolor4f_vertexbuffer = 0;
12256         rsurface.passcolor4f_bufferoffset = 0;
12257 }
12258
12259 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12260 {
12261         int i;
12262         float f;
12263         const float *v;
12264         const float *c;
12265         float *c2;
12266         if (!rsurface.passcolor4f)
12267                 return;
12268         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
12269         {
12270                 f = RSurf_FogVertex(v);
12271                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12272                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12273                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12274                 c2[3] = c[3];
12275         }
12276         rsurface.passcolor4f = rsurface.array_passcolor4f;
12277         rsurface.passcolor4f_vertexbuffer = 0;
12278         rsurface.passcolor4f_bufferoffset = 0;
12279 }
12280
12281 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12282 {
12283         int i;
12284         const float *c;
12285         float *c2;
12286         if (!rsurface.passcolor4f)
12287                 return;
12288         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12289         {
12290                 c2[0] = c[0] * r;
12291                 c2[1] = c[1] * g;
12292                 c2[2] = c[2] * b;
12293                 c2[3] = c[3] * a;
12294         }
12295         rsurface.passcolor4f = rsurface.array_passcolor4f;
12296         rsurface.passcolor4f_vertexbuffer = 0;
12297         rsurface.passcolor4f_bufferoffset = 0;
12298 }
12299
12300 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12301 {
12302         int i;
12303         const float *c;
12304         float *c2;
12305         if (!rsurface.passcolor4f)
12306                 return;
12307         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12308         {
12309                 c2[0] = c[0] + r_refdef.scene.ambient;
12310                 c2[1] = c[1] + r_refdef.scene.ambient;
12311                 c2[2] = c[2] + r_refdef.scene.ambient;
12312                 c2[3] = c[3];
12313         }
12314         rsurface.passcolor4f = rsurface.array_passcolor4f;
12315         rsurface.passcolor4f_vertexbuffer = 0;
12316         rsurface.passcolor4f_bufferoffset = 0;
12317 }
12318
12319 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12320 {
12321         // TODO: optimize
12322         rsurface.passcolor4f = NULL;
12323         rsurface.passcolor4f_vertexbuffer = 0;
12324         rsurface.passcolor4f_bufferoffset = 0;
12325         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12326         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12327         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12328         GL_Color(r, g, b, a);
12329         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12330         RSurf_DrawBatch();
12331 }
12332
12333 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12334 {
12335         // TODO: optimize applyfog && applycolor case
12336         // just apply fog if necessary, and tint the fog color array if necessary
12337         rsurface.passcolor4f = NULL;
12338         rsurface.passcolor4f_vertexbuffer = 0;
12339         rsurface.passcolor4f_bufferoffset = 0;
12340         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12341         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12342         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12343         GL_Color(r, g, b, a);
12344         RSurf_DrawBatch();
12345 }
12346
12347 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12348 {
12349         // TODO: optimize
12350         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12351         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12352         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12353         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12354         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12355         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12356         GL_Color(r, g, b, a);
12357         RSurf_DrawBatch();
12358 }
12359
12360 static void RSurf_DrawBatch_GL11_ClampColor(void)
12361 {
12362         int i;
12363         const float *c1;
12364         float *c2;
12365         if (!rsurface.passcolor4f)
12366                 return;
12367         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12368         {
12369                 c2[0] = bound(0.0f, c1[0], 1.0f);
12370                 c2[1] = bound(0.0f, c1[1], 1.0f);
12371                 c2[2] = bound(0.0f, c1[2], 1.0f);
12372                 c2[3] = bound(0.0f, c1[3], 1.0f);
12373         }
12374 }
12375
12376 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12377 {
12378         int i;
12379         float f;
12380         const float *v;
12381         const float *n;
12382         float *c;
12383         //vec3_t eyedir;
12384
12385         // fake shading
12386         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
12387         {
12388                 f = -DotProduct(r_refdef.view.forward, n);
12389                 f = max(0, f);
12390                 f = f * 0.85 + 0.15; // work around so stuff won't get black
12391                 f *= r_refdef.lightmapintensity;
12392                 Vector4Set(c, f, f, f, 1);
12393         }
12394
12395         rsurface.passcolor4f = rsurface.array_passcolor4f;
12396         rsurface.passcolor4f_vertexbuffer = 0;
12397         rsurface.passcolor4f_bufferoffset = 0;
12398 }
12399
12400 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12401 {
12402         RSurf_DrawBatch_GL11_ApplyFakeLight();
12403         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12404         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12405         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12406         GL_Color(r, g, b, a);
12407         RSurf_DrawBatch();
12408 }
12409
12410 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12411 {
12412         int i;
12413         float f;
12414         float alpha;
12415         const float *v;
12416         const float *n;
12417         float *c;
12418         vec3_t ambientcolor;
12419         vec3_t diffusecolor;
12420         vec3_t lightdir;
12421         // TODO: optimize
12422         // model lighting
12423         VectorCopy(rsurface.modellight_lightdir, lightdir);
12424         f = 0.5f * r_refdef.lightmapintensity;
12425         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12426         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12427         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12428         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12429         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12430         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12431         alpha = *a;
12432         if (VectorLength2(diffusecolor) > 0)
12433         {
12434                 // q3-style directional shading
12435                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
12436                 {
12437                         if ((f = DotProduct(n, lightdir)) > 0)
12438                                 VectorMA(ambientcolor, f, diffusecolor, c);
12439                         else
12440                                 VectorCopy(ambientcolor, c);
12441                         c[3] = alpha;
12442                 }
12443                 *r = 1;
12444                 *g = 1;
12445                 *b = 1;
12446                 *a = 1;
12447                 rsurface.passcolor4f = rsurface.array_passcolor4f;
12448                 rsurface.passcolor4f_vertexbuffer = 0;
12449                 rsurface.passcolor4f_bufferoffset = 0;
12450                 *applycolor = false;
12451         }
12452         else
12453         {
12454                 *r = ambientcolor[0];
12455                 *g = ambientcolor[1];
12456                 *b = ambientcolor[2];
12457                 rsurface.passcolor4f = NULL;
12458                 rsurface.passcolor4f_vertexbuffer = 0;
12459                 rsurface.passcolor4f_bufferoffset = 0;
12460         }
12461 }
12462
12463 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12464 {
12465         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12466         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12467         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12468         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12469         GL_Color(r, g, b, a);
12470         RSurf_DrawBatch();
12471 }
12472
12473 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12474 {
12475         int i;
12476         float f;
12477         const float *v;
12478         float *c;
12479         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12480         {
12481                 f = 1 - RSurf_FogVertex(v);
12482                 c[0] = r;
12483                 c[1] = g;
12484                 c[2] = b;
12485                 c[3] = f * a;
12486         }
12487 }
12488
12489 void RSurf_SetupDepthAndCulling(void)
12490 {
12491         // submodels are biased to avoid z-fighting with world surfaces that they
12492         // may be exactly overlapping (avoids z-fighting artifacts on certain
12493         // doors and things in Quake maps)
12494         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12495         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12496         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12497         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12498 }
12499
12500 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12501 {
12502         // transparent sky would be ridiculous
12503         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12504                 return;
12505         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12506         skyrenderlater = true;
12507         RSurf_SetupDepthAndCulling();
12508         GL_DepthMask(true);
12509         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12510         // skymasking on them, and Quake3 never did sky masking (unlike
12511         // software Quake and software Quake2), so disable the sky masking
12512         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12513         // and skymasking also looks very bad when noclipping outside the
12514         // level, so don't use it then either.
12515         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12516         {
12517                 R_Mesh_ResetTextureState();
12518                 if (skyrendermasked)
12519                 {
12520                         R_SetupShader_DepthOrShadow();
12521                         // depth-only (masking)
12522                         GL_ColorMask(0,0,0,0);
12523                         // just to make sure that braindead drivers don't draw
12524                         // anything despite that colormask...
12525                         GL_BlendFunc(GL_ZERO, GL_ONE);
12526                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12527                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12528                 }
12529                 else
12530                 {
12531                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12532                         // fog sky
12533                         GL_BlendFunc(GL_ONE, GL_ZERO);
12534                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12535                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12536                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12537                 }
12538                 RSurf_DrawBatch();
12539                 if (skyrendermasked)
12540                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12541         }
12542         R_Mesh_ResetTextureState();
12543         GL_Color(1, 1, 1, 1);
12544 }
12545
12546 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12547 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12548 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12549 {
12550         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12551                 return;
12552         if (prepass)
12553         {
12554                 // render screenspace normalmap to texture
12555                 GL_DepthMask(true);
12556                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12557                 RSurf_DrawBatch();
12558                 return;
12559         }
12560
12561         // bind lightmap texture
12562
12563         // water/refraction/reflection/camera surfaces have to be handled specially
12564         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12565         {
12566                 int start, end, startplaneindex;
12567                 for (start = 0;start < texturenumsurfaces;start = end)
12568                 {
12569                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12570                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12571                                 ;
12572                         // now that we have a batch using the same planeindex, render it
12573                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12574                         {
12575                                 // render water or distortion background
12576                                 GL_DepthMask(true);
12577                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex));
12578                                 RSurf_DrawBatch();
12579                                 // blend surface on top
12580                                 GL_DepthMask(false);
12581                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12582                                 RSurf_DrawBatch();
12583                         }
12584                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12585                         {
12586                                 // render surface with reflection texture as input
12587                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12588                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex));
12589                                 RSurf_DrawBatch();
12590                         }
12591                 }
12592                 return;
12593         }
12594
12595         // render surface batch normally
12596         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12597         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12598         RSurf_DrawBatch();
12599 }
12600
12601 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12602 {
12603         // OpenGL 1.3 path - anything not completely ancient
12604         qboolean applycolor;
12605         qboolean applyfog;
12606         int layerindex;
12607         const texturelayer_t *layer;
12608         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12609         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12610
12611         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12612         {
12613                 vec4_t layercolor;
12614                 int layertexrgbscale;
12615                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12616                 {
12617                         if (layerindex == 0)
12618                                 GL_AlphaTest(true);
12619                         else
12620                         {
12621                                 GL_AlphaTest(false);
12622                                 GL_DepthFunc(GL_EQUAL);
12623                         }
12624                 }
12625                 GL_DepthMask(layer->depthmask && writedepth);
12626                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12627                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12628                 {
12629                         layertexrgbscale = 4;
12630                         VectorScale(layer->color, 0.25f, layercolor);
12631                 }
12632                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12633                 {
12634                         layertexrgbscale = 2;
12635                         VectorScale(layer->color, 0.5f, layercolor);
12636                 }
12637                 else
12638                 {
12639                         layertexrgbscale = 1;
12640                         VectorScale(layer->color, 1.0f, layercolor);
12641                 }
12642                 layercolor[3] = layer->color[3];
12643                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12644                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12645                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12646                 switch (layer->type)
12647                 {
12648                 case TEXTURELAYERTYPE_LITTEXTURE:
12649                         // single-pass lightmapped texture with 2x rgbscale
12650                         R_Mesh_TexBind(0, r_texture_white);
12651                         R_Mesh_TexMatrix(0, NULL);
12652                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12653                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12654                         R_Mesh_TexBind(1, layer->texture);
12655                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12656                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12657                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12658                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12659                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12660                         else if (FAKELIGHT_ENABLED)
12661                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12662                         else if (rsurface.uselightmaptexture)
12663                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12664                         else
12665                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12666                         break;
12667                 case TEXTURELAYERTYPE_TEXTURE:
12668                         // singletexture unlit texture with transparency support
12669                         R_Mesh_TexBind(0, layer->texture);
12670                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12671                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12672                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12673                         R_Mesh_TexBind(1, 0);
12674                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12675                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12676                         break;
12677                 case TEXTURELAYERTYPE_FOG:
12678                         // singletexture fogging
12679                         if (layer->texture)
12680                         {
12681                                 R_Mesh_TexBind(0, layer->texture);
12682                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12683                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12684                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12685                         }
12686                         else
12687                         {
12688                                 R_Mesh_TexBind(0, 0);
12689                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12690                         }
12691                         R_Mesh_TexBind(1, 0);
12692                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12693                         // generate a color array for the fog pass
12694                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12695                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12696                         RSurf_DrawBatch();
12697                         break;
12698                 default:
12699                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12700                 }
12701         }
12702         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12703         {
12704                 GL_DepthFunc(GL_LEQUAL);
12705                 GL_AlphaTest(false);
12706         }
12707 }
12708
12709 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12710 {
12711         // OpenGL 1.1 - crusty old voodoo path
12712         qboolean applyfog;
12713         int layerindex;
12714         const texturelayer_t *layer;
12715         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12716         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12717
12718         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12719         {
12720                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12721                 {
12722                         if (layerindex == 0)
12723                                 GL_AlphaTest(true);
12724                         else
12725                         {
12726                                 GL_AlphaTest(false);
12727                                 GL_DepthFunc(GL_EQUAL);
12728                         }
12729                 }
12730                 GL_DepthMask(layer->depthmask && writedepth);
12731                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12732                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12733                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12734                 switch (layer->type)
12735                 {
12736                 case TEXTURELAYERTYPE_LITTEXTURE:
12737                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12738                         {
12739                                 // two-pass lit texture with 2x rgbscale
12740                                 // first the lightmap pass
12741                                 R_Mesh_TexBind(0, r_texture_white);
12742                                 R_Mesh_TexMatrix(0, NULL);
12743                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12744                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12745                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12746                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12747                                 else if (FAKELIGHT_ENABLED)
12748                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12749                                 else if (rsurface.uselightmaptexture)
12750                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12751                                 else
12752                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12753                                 // then apply the texture to it
12754                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12755                                 R_Mesh_TexBind(0, layer->texture);
12756                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12757                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12758                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12759                                 RSurf_DrawBatch_GL11_Unlit(layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
12760                         }
12761                         else
12762                         {
12763                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12764                                 R_Mesh_TexBind(0, layer->texture);
12765                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12766                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12767                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12768                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12769                                         RSurf_DrawBatch_GL11_VertexShade(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
12770                                 else
12771                                         RSurf_DrawBatch_GL11_VertexColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
12772                         }
12773                         break;
12774                 case TEXTURELAYERTYPE_TEXTURE:
12775                         // singletexture unlit texture with transparency support
12776                         R_Mesh_TexBind(0, layer->texture);
12777                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12778                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12779                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12780                         RSurf_DrawBatch_GL11_Unlit(layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
12781                         break;
12782                 case TEXTURELAYERTYPE_FOG:
12783                         // singletexture fogging
12784                         if (layer->texture)
12785                         {
12786                                 R_Mesh_TexBind(0, layer->texture);
12787                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12788                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12789                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12790                         }
12791                         else
12792                         {
12793                                 R_Mesh_TexBind(0, 0);
12794                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12795                         }
12796                         // generate a color array for the fog pass
12797                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12798                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12799                         RSurf_DrawBatch();
12800                         break;
12801                 default:
12802                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12803                 }
12804         }
12805         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12806         {
12807                 GL_DepthFunc(GL_LEQUAL);
12808                 GL_AlphaTest(false);
12809         }
12810 }
12811
12812 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12813 {
12814         int vi;
12815         int j;
12816         r_vertexgeneric_t *batchvertex;
12817         float c[4];
12818
12819         GL_AlphaTest(false);
12820         R_Mesh_ResetTextureState();
12821         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12822
12823         if(rsurface.texture && rsurface.texture->currentskinframe)
12824         {
12825                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12826                 c[3] *= rsurface.texture->currentalpha;
12827         }
12828         else
12829         {
12830                 c[0] = 1;
12831                 c[1] = 0;
12832                 c[2] = 1;
12833                 c[3] = 1;
12834         }
12835
12836         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12837         {
12838                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12839                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12840                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12841         }
12842
12843         // brighten it up (as texture value 127 means "unlit")
12844         c[0] *= 2 * r_refdef.view.colorscale;
12845         c[1] *= 2 * r_refdef.view.colorscale;
12846         c[2] *= 2 * r_refdef.view.colorscale;
12847
12848         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12849                 c[3] *= r_wateralpha.value;
12850
12851         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12852         {
12853                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12854                 GL_DepthMask(false);
12855         }
12856         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12857         {
12858                 GL_BlendFunc(GL_ONE, GL_ONE);
12859                 GL_DepthMask(false);
12860         }
12861         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12862         {
12863                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12864                 GL_DepthMask(false);
12865         }
12866         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12867         {
12868                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12869                 GL_DepthMask(false);
12870         }
12871         else
12872         {
12873                 GL_BlendFunc(GL_ONE, GL_ZERO);
12874                 GL_DepthMask(writedepth);
12875         }
12876
12877         if (r_showsurfaces.integer == 3)
12878         {
12879                 rsurface.passcolor4f = NULL;
12880
12881                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12882                 {
12883                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12884
12885                         rsurface.passcolor4f = NULL;
12886                         rsurface.passcolor4f_vertexbuffer = 0;
12887                         rsurface.passcolor4f_bufferoffset = 0;
12888                 }
12889                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12890                 {
12891                         qboolean applycolor = true;
12892                         float one = 1.0;
12893
12894                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12895
12896                         r_refdef.lightmapintensity = 1;
12897                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12898                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12899                 }
12900                 else if (FAKELIGHT_ENABLED)
12901                 {
12902                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12903
12904                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
12905                         RSurf_DrawBatch_GL11_ApplyFakeLight();
12906                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12907                 }
12908                 else
12909                 {
12910                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12911
12912                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12913                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12914                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12915                 }
12916
12917                 if(!rsurface.passcolor4f)
12918                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12919
12920                 RSurf_DrawBatch_GL11_ApplyAmbient();
12921                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12922                 if(r_refdef.fogenabled)
12923                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12924                 RSurf_DrawBatch_GL11_ClampColor();
12925
12926                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12927                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12928                 RSurf_DrawBatch();
12929         }
12930         else if (!r_refdef.view.showdebug)
12931         {
12932                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12933                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12934                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12935                 {
12936                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12937                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12938                 }
12939                 R_Mesh_PrepareVertices_Generic_Unlock();
12940                 RSurf_DrawBatch();
12941         }
12942         else if (r_showsurfaces.integer == 4)
12943         {
12944                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12945                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12946                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12947                 {
12948                         unsigned char c = vi << 3;
12949                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12950                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12951                 }
12952                 R_Mesh_PrepareVertices_Generic_Unlock();
12953                 RSurf_DrawBatch();
12954         }
12955         else if (r_showsurfaces.integer == 2)
12956         {
12957                 const int *e;
12958                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12959                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12960                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12961                 {
12962                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12963                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12964                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12965                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12966                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12967                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12968                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12969                 }
12970                 R_Mesh_PrepareVertices_Generic_Unlock();
12971                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12972         }
12973         else
12974         {
12975                 int texturesurfaceindex;
12976                 int k;
12977                 const msurface_t *surface;
12978                 unsigned char surfacecolor4ub[4];
12979                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12980                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12981                 vi = 0;
12982                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12983                 {
12984                         surface = texturesurfacelist[texturesurfaceindex];
12985                         k = (int)(((size_t)surface) / sizeof(msurface_t));
12986                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12987                         for (j = 0;j < surface->num_vertices;j++)
12988                         {
12989                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12990                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12991                                 vi++;
12992                         }
12993                 }
12994                 R_Mesh_PrepareVertices_Generic_Unlock();
12995                 RSurf_DrawBatch();
12996         }
12997 }
12998
12999 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13000 {
13001         CHECKGLERROR
13002         RSurf_SetupDepthAndCulling();
13003         if (r_showsurfaces.integer)
13004         {
13005                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13006                 return;
13007         }
13008         switch (vid.renderpath)
13009         {
13010         case RENDERPATH_GL20:
13011         case RENDERPATH_CGGL:
13012         case RENDERPATH_D3D9:
13013         case RENDERPATH_D3D10:
13014         case RENDERPATH_D3D11:
13015                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13016                 break;
13017         case RENDERPATH_GL13:
13018                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13019                 break;
13020         case RENDERPATH_GL11:
13021                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13022                 break;
13023         }
13024         CHECKGLERROR
13025 }
13026
13027 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13028 {
13029         CHECKGLERROR
13030         RSurf_SetupDepthAndCulling();
13031         if (r_showsurfaces.integer)
13032         {
13033                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13034                 return;
13035         }
13036         switch (vid.renderpath)
13037         {
13038         case RENDERPATH_GL20:
13039         case RENDERPATH_CGGL:
13040         case RENDERPATH_D3D9:
13041         case RENDERPATH_D3D10:
13042         case RENDERPATH_D3D11:
13043                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13044                 break;
13045         case RENDERPATH_GL13:
13046                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13047                 break;
13048         case RENDERPATH_GL11:
13049                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13050                 break;
13051         }
13052         CHECKGLERROR
13053 }
13054
13055 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13056 {
13057         int i, j;
13058         int texturenumsurfaces, endsurface;
13059         texture_t *texture;
13060         const msurface_t *surface;
13061 #define MAXBATCH_TRANSPARENTSURFACES 256
13062         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13063
13064         // if the model is static it doesn't matter what value we give for
13065         // wantnormals and wanttangents, so this logic uses only rules applicable
13066         // to a model, knowing that they are meaningless otherwise
13067         if (ent == r_refdef.scene.worldentity)
13068                 RSurf_ActiveWorldEntity();
13069         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13070                 RSurf_ActiveModelEntity(ent, false, false, false);
13071         else
13072         {
13073                 switch (vid.renderpath)
13074                 {
13075                 case RENDERPATH_GL20:
13076                 case RENDERPATH_CGGL:
13077                 case RENDERPATH_D3D9:
13078                 case RENDERPATH_D3D10:
13079                 case RENDERPATH_D3D11:
13080                         RSurf_ActiveModelEntity(ent, true, true, false);
13081                         break;
13082                 case RENDERPATH_GL13:
13083                 case RENDERPATH_GL11:
13084                         RSurf_ActiveModelEntity(ent, true, false, false);
13085                         break;
13086                 }
13087         }
13088
13089         if (r_transparentdepthmasking.integer)
13090         {
13091                 qboolean setup = false;
13092                 for (i = 0;i < numsurfaces;i = j)
13093                 {
13094                         j = i + 1;
13095                         surface = rsurface.modelsurfaces + surfacelist[i];
13096                         texture = surface->texture;
13097                         rsurface.texture = R_GetCurrentTexture(texture);
13098                         rsurface.lightmaptexture = NULL;
13099                         rsurface.deluxemaptexture = NULL;
13100                         rsurface.uselightmaptexture = false;
13101                         // scan ahead until we find a different texture
13102                         endsurface = min(i + 1024, numsurfaces);
13103                         texturenumsurfaces = 0;
13104                         texturesurfacelist[texturenumsurfaces++] = surface;
13105                         for (;j < endsurface;j++)
13106                         {
13107                                 surface = rsurface.modelsurfaces + surfacelist[j];
13108                                 if (texture != surface->texture)
13109                                         break;
13110                                 texturesurfacelist[texturenumsurfaces++] = surface;
13111                         }
13112                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13113                                 continue;
13114                         // render the range of surfaces as depth
13115                         if (!setup)
13116                         {
13117                                 setup = true;
13118                                 GL_ColorMask(0,0,0,0);
13119                                 GL_Color(1,1,1,1);
13120                                 GL_DepthTest(true);
13121                                 GL_BlendFunc(GL_ONE, GL_ZERO);
13122                                 GL_DepthMask(true);
13123                                 GL_AlphaTest(false);
13124                                 R_Mesh_ResetTextureState();
13125                                 R_SetupShader_DepthOrShadow();
13126                         }
13127                         RSurf_SetupDepthAndCulling();
13128                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13129                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13130                         RSurf_DrawBatch();
13131                 }
13132                 if (setup)
13133                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13134         }
13135
13136         for (i = 0;i < numsurfaces;i = j)
13137         {
13138                 j = i + 1;
13139                 surface = rsurface.modelsurfaces + surfacelist[i];
13140                 texture = surface->texture;
13141                 rsurface.texture = R_GetCurrentTexture(texture);
13142                 // scan ahead until we find a different texture
13143                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13144                 texturenumsurfaces = 0;
13145                 texturesurfacelist[texturenumsurfaces++] = surface;
13146                 if(FAKELIGHT_ENABLED)
13147                 {
13148                         rsurface.lightmaptexture = NULL;
13149                         rsurface.deluxemaptexture = NULL;
13150                         rsurface.uselightmaptexture = false;
13151                         for (;j < endsurface;j++)
13152                         {
13153                                 surface = rsurface.modelsurfaces + surfacelist[j];
13154                                 if (texture != surface->texture)
13155                                         break;
13156                                 texturesurfacelist[texturenumsurfaces++] = surface;
13157                         }
13158                 }
13159                 else
13160                 {
13161                         rsurface.lightmaptexture = surface->lightmaptexture;
13162                         rsurface.deluxemaptexture = surface->deluxemaptexture;
13163                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13164                         for (;j < endsurface;j++)
13165                         {
13166                                 surface = rsurface.modelsurfaces + surfacelist[j];
13167                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13168                                         break;
13169                                 texturesurfacelist[texturenumsurfaces++] = surface;
13170                         }
13171                 }
13172                 // render the range of surfaces
13173                 if (ent == r_refdef.scene.worldentity)
13174                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13175                 else
13176                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13177         }
13178         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13179         GL_AlphaTest(false);
13180 }
13181
13182 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13183 {
13184         // transparent surfaces get pushed off into the transparent queue
13185         int surfacelistindex;
13186         const msurface_t *surface;
13187         vec3_t tempcenter, center;
13188         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13189         {
13190                 surface = texturesurfacelist[surfacelistindex];
13191                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13192                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13193                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13194                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13195                 if (queueentity->transparent_offset) // transparent offset
13196                 {
13197                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13198                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13199                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13200                 }
13201                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13202         }
13203 }
13204
13205 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13206 {
13207         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13208                 return;
13209         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13210                 return;
13211         RSurf_SetupDepthAndCulling();
13212         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13213         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13214         RSurf_DrawBatch();
13215 }
13216
13217 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13218 {
13219         const entity_render_t *queueentity = r_refdef.scene.worldentity;
13220         CHECKGLERROR
13221         if (depthonly)
13222                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13223         else if (prepass)
13224         {
13225                 if (!rsurface.texture->currentnumlayers)
13226                         return;
13227                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13228                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13229                 else
13230                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13231         }
13232         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13233                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13234         else if (!rsurface.texture->currentnumlayers)
13235                 return;
13236         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13237         {
13238                 // in the deferred case, transparent surfaces were queued during prepass
13239                 if (!r_shadow_usingdeferredprepass)
13240                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13241         }
13242         else
13243         {
13244                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13245                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13246         }
13247         CHECKGLERROR
13248 }
13249
13250 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13251 {
13252         int i, j;
13253         texture_t *texture;
13254         // break the surface list down into batches by texture and use of lightmapping
13255         for (i = 0;i < numsurfaces;i = j)
13256         {
13257                 j = i + 1;
13258                 // texture is the base texture pointer, rsurface.texture is the
13259                 // current frame/skin the texture is directing us to use (for example
13260                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13261                 // use skin 1 instead)
13262                 texture = surfacelist[i]->texture;
13263                 rsurface.texture = R_GetCurrentTexture(texture);
13264                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13265                 {
13266                         // if this texture is not the kind we want, skip ahead to the next one
13267                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13268                                 ;
13269                         continue;
13270                 }
13271                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13272                 {
13273                         rsurface.lightmaptexture = NULL;
13274                         rsurface.deluxemaptexture = NULL;
13275                         rsurface.uselightmaptexture = false;
13276                         // simply scan ahead until we find a different texture or lightmap state
13277                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13278                                 ;
13279                 }
13280                 else
13281                 {
13282                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13283                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13284                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13285                         // simply scan ahead until we find a different texture or lightmap state
13286                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13287                                 ;
13288                 }
13289                 // render the range of surfaces
13290                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13291         }
13292 }
13293
13294 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13295 {
13296         CHECKGLERROR
13297         if (depthonly)
13298                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13299         else if (prepass)
13300         {
13301                 if (!rsurface.texture->currentnumlayers)
13302                         return;
13303                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13304                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13305                 else
13306                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13307         }
13308         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13309                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13310         else if (!rsurface.texture->currentnumlayers)
13311                 return;
13312         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13313         {
13314                 // in the deferred case, transparent surfaces were queued during prepass
13315                 if (!r_shadow_usingdeferredprepass)
13316                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13317         }
13318         else
13319         {
13320                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13321                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13322         }
13323         CHECKGLERROR
13324 }
13325
13326 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13327 {
13328         int i, j;
13329         texture_t *texture;
13330         // break the surface list down into batches by texture and use of lightmapping
13331         for (i = 0;i < numsurfaces;i = j)
13332         {
13333                 j = i + 1;
13334                 // texture is the base texture pointer, rsurface.texture is the
13335                 // current frame/skin the texture is directing us to use (for example
13336                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13337                 // use skin 1 instead)
13338                 texture = surfacelist[i]->texture;
13339                 rsurface.texture = R_GetCurrentTexture(texture);
13340                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13341                 {
13342                         // if this texture is not the kind we want, skip ahead to the next one
13343                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13344                                 ;
13345                         continue;
13346                 }
13347                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13348                 {
13349                         rsurface.lightmaptexture = NULL;
13350                         rsurface.deluxemaptexture = NULL;
13351                         rsurface.uselightmaptexture = false;
13352                         // simply scan ahead until we find a different texture or lightmap state
13353                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13354                                 ;
13355                 }
13356                 else
13357                 {
13358                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13359                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13360                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13361                         // simply scan ahead until we find a different texture or lightmap state
13362                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13363                                 ;
13364                 }
13365                 // render the range of surfaces
13366                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13367         }
13368 }
13369
13370 float locboxvertex3f[6*4*3] =
13371 {
13372         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13373         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13374         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13375         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13376         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13377         1,0,0, 0,0,0, 0,1,0, 1,1,0
13378 };
13379
13380 unsigned short locboxelements[6*2*3] =
13381 {
13382          0, 1, 2, 0, 2, 3,
13383          4, 5, 6, 4, 6, 7,
13384          8, 9,10, 8,10,11,
13385         12,13,14, 12,14,15,
13386         16,17,18, 16,18,19,
13387         20,21,22, 20,22,23
13388 };
13389
13390 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13391 {
13392         int i, j;
13393         cl_locnode_t *loc = (cl_locnode_t *)ent;
13394         vec3_t mins, size;
13395         float vertex3f[6*4*3];
13396         CHECKGLERROR
13397         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13398         GL_DepthMask(false);
13399         GL_DepthRange(0, 1);
13400         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13401         GL_DepthTest(true);
13402         GL_CullFace(GL_NONE);
13403         R_EntityMatrix(&identitymatrix);
13404
13405         R_Mesh_ResetTextureState();
13406
13407         i = surfacelist[0];
13408         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13409                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13410                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13411                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13412
13413         if (VectorCompare(loc->mins, loc->maxs))
13414         {
13415                 VectorSet(size, 2, 2, 2);
13416                 VectorMA(loc->mins, -0.5f, size, mins);
13417         }
13418         else
13419         {
13420                 VectorCopy(loc->mins, mins);
13421                 VectorSubtract(loc->maxs, loc->mins, size);
13422         }
13423
13424         for (i = 0;i < 6*4*3;)
13425                 for (j = 0;j < 3;j++, i++)
13426                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13427
13428         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13429         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13430         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13431 }
13432
13433 void R_DrawLocs(void)
13434 {
13435         int index;
13436         cl_locnode_t *loc, *nearestloc;
13437         vec3_t center;
13438         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13439         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13440         {
13441                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13442                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13443         }
13444 }
13445
13446 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13447 {
13448         if (decalsystem->decals)
13449                 Mem_Free(decalsystem->decals);
13450         memset(decalsystem, 0, sizeof(*decalsystem));
13451 }
13452
13453 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)
13454 {
13455         tridecal_t *decal;
13456         tridecal_t *decals;
13457         int i;
13458
13459         // expand or initialize the system
13460         if (decalsystem->maxdecals <= decalsystem->numdecals)
13461         {
13462                 decalsystem_t old = *decalsystem;
13463                 qboolean useshortelements;
13464                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13465                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13466                 decalsystem->decals = (tridecal_t *)Mem_Alloc(cls.levelmempool, decalsystem->maxdecals * (sizeof(tridecal_t) + sizeof(float[3][3]) + sizeof(float[3][2]) + sizeof(float[3][4]) + sizeof(int[3]) + (useshortelements ? sizeof(unsigned short[3]) : 0)));
13467                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13468                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13469                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13470                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13471                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13472                 if (decalsystem->numdecals)
13473                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13474                 if (old.decals)
13475                         Mem_Free(old.decals);
13476                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13477                         decalsystem->element3i[i] = i;
13478                 if (useshortelements)
13479                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13480                                 decalsystem->element3s[i] = i;
13481         }
13482
13483         // grab a decal and search for another free slot for the next one
13484         decals = decalsystem->decals;
13485         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13486         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13487                 ;
13488         decalsystem->freedecal = i;
13489         if (decalsystem->numdecals <= i)
13490                 decalsystem->numdecals = i + 1;
13491
13492         // initialize the decal
13493         decal->lived = 0;
13494         decal->triangleindex = triangleindex;
13495         decal->surfaceindex = surfaceindex;
13496         decal->decalsequence = decalsequence;
13497         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13498         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13499         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13500         decal->color4ub[0][3] = 255;
13501         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13502         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13503         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13504         decal->color4ub[1][3] = 255;
13505         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13506         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13507         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13508         decal->color4ub[2][3] = 255;
13509         decal->vertex3f[0][0] = v0[0];
13510         decal->vertex3f[0][1] = v0[1];
13511         decal->vertex3f[0][2] = v0[2];
13512         decal->vertex3f[1][0] = v1[0];
13513         decal->vertex3f[1][1] = v1[1];
13514         decal->vertex3f[1][2] = v1[2];
13515         decal->vertex3f[2][0] = v2[0];
13516         decal->vertex3f[2][1] = v2[1];
13517         decal->vertex3f[2][2] = v2[2];
13518         decal->texcoord2f[0][0] = t0[0];
13519         decal->texcoord2f[0][1] = t0[1];
13520         decal->texcoord2f[1][0] = t1[0];
13521         decal->texcoord2f[1][1] = t1[1];
13522         decal->texcoord2f[2][0] = t2[0];
13523         decal->texcoord2f[2][1] = t2[1];
13524 }
13525
13526 extern cvar_t cl_decals_bias;
13527 extern cvar_t cl_decals_models;
13528 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13529 // baseparms, parms, temps
13530 static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
13531 {
13532         int cornerindex;
13533         int index;
13534         float v[9][3];
13535         const float *vertex3f;
13536         int numpoints;
13537         float points[2][9][3];
13538         float temp[3];
13539         float tc[9][2];
13540         float f;
13541         float c[9][4];
13542         const int *e;
13543
13544         e = rsurface.modelelement3i + 3*triangleindex;
13545
13546         vertex3f = rsurface.modelvertex3f;
13547
13548         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13549         {
13550                 index = 3*e[cornerindex];
13551                 VectorCopy(vertex3f + index, v[cornerindex]);
13552         }
13553         // cull backfaces
13554         //TriangleNormal(v[0], v[1], v[2], normal);
13555         //if (DotProduct(normal, localnormal) < 0.0f)
13556         //      continue;
13557         // clip by each of the box planes formed from the projection matrix
13558         // if anything survives, we emit the decal
13559         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]);
13560         if (numpoints < 3)
13561                 return;
13562         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]);
13563         if (numpoints < 3)
13564                 return;
13565         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]);
13566         if (numpoints < 3)
13567                 return;
13568         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]);
13569         if (numpoints < 3)
13570                 return;
13571         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]);
13572         if (numpoints < 3)
13573                 return;
13574         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]);
13575         if (numpoints < 3)
13576                 return;
13577         // some part of the triangle survived, so we have to accept it...
13578         if (dynamic)
13579         {
13580                 // dynamic always uses the original triangle
13581                 numpoints = 3;
13582                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13583                 {
13584                         index = 3*e[cornerindex];
13585                         VectorCopy(vertex3f + index, v[cornerindex]);
13586                 }
13587         }
13588         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13589         {
13590                 // convert vertex positions to texcoords
13591                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13592                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13593                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13594                 // calculate distance fade from the projection origin
13595                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13596                 f = bound(0.0f, f, 1.0f);
13597                 c[cornerindex][0] = r * f;
13598                 c[cornerindex][1] = g * f;
13599                 c[cornerindex][2] = b * f;
13600                 c[cornerindex][3] = 1.0f;
13601                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13602         }
13603         if (dynamic)
13604                 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex, surfaceindex, decalsequence);
13605         else
13606                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13607                         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);
13608 }
13609 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)
13610 {
13611         matrix4x4_t projection;
13612         decalsystem_t *decalsystem;
13613         qboolean dynamic;
13614         dp_model_t *model;
13615         const msurface_t *surface;
13616         const msurface_t *surfaces;
13617         const int *surfacelist;
13618         const texture_t *texture;
13619         int numtriangles;
13620         int numsurfacelist;
13621         int surfacelistindex;
13622         int surfaceindex;
13623         int triangleindex;
13624         float localorigin[3];
13625         float localnormal[3];
13626         float localmins[3];
13627         float localmaxs[3];
13628         float localsize;
13629         //float normal[3];
13630         float planes[6][4];
13631         float angles[3];
13632         bih_t *bih;
13633         int bih_triangles_count;
13634         int bih_triangles[256];
13635         int bih_surfaces[256];
13636
13637         decalsystem = &ent->decalsystem;
13638         model = ent->model;
13639         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13640         {
13641                 R_DecalSystem_Reset(&ent->decalsystem);
13642                 return;
13643         }
13644
13645         if (!model->brush.data_leafs && !cl_decals_models.integer)
13646         {
13647                 if (decalsystem->model)
13648                         R_DecalSystem_Reset(decalsystem);
13649                 return;
13650         }
13651
13652         if (decalsystem->model != model)
13653                 R_DecalSystem_Reset(decalsystem);
13654         decalsystem->model = model;
13655
13656         RSurf_ActiveModelEntity(ent, false, false, false);
13657
13658         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13659         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13660         VectorNormalize(localnormal);
13661         localsize = worldsize*rsurface.inversematrixscale;
13662         localmins[0] = localorigin[0] - localsize;
13663         localmins[1] = localorigin[1] - localsize;
13664         localmins[2] = localorigin[2] - localsize;
13665         localmaxs[0] = localorigin[0] + localsize;
13666         localmaxs[1] = localorigin[1] + localsize;
13667         localmaxs[2] = localorigin[2] + localsize;
13668
13669         //VectorCopy(localnormal, planes[4]);
13670         //VectorVectors(planes[4], planes[2], planes[0]);
13671         AnglesFromVectors(angles, localnormal, NULL, false);
13672         AngleVectors(angles, planes[0], planes[2], planes[4]);
13673         VectorNegate(planes[0], planes[1]);
13674         VectorNegate(planes[2], planes[3]);
13675         VectorNegate(planes[4], planes[5]);
13676         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13677         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13678         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13679         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13680         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13681         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13682
13683 #if 1
13684 // works
13685 {
13686         matrix4x4_t forwardprojection;
13687         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13688         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13689 }
13690 #else
13691 // broken
13692 {
13693         float projectionvector[4][3];
13694         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13695         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13696         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13697         projectionvector[0][0] = planes[0][0] * ilocalsize;
13698         projectionvector[0][1] = planes[1][0] * ilocalsize;
13699         projectionvector[0][2] = planes[2][0] * ilocalsize;
13700         projectionvector[1][0] = planes[0][1] * ilocalsize;
13701         projectionvector[1][1] = planes[1][1] * ilocalsize;
13702         projectionvector[1][2] = planes[2][1] * ilocalsize;
13703         projectionvector[2][0] = planes[0][2] * ilocalsize;
13704         projectionvector[2][1] = planes[1][2] * ilocalsize;
13705         projectionvector[2][2] = planes[2][2] * ilocalsize;
13706         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13707         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13708         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13709         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13710 }
13711 #endif
13712
13713         dynamic = model->surfmesh.isanimated;
13714         numsurfacelist = model->nummodelsurfaces;
13715         surfacelist = model->sortedmodelsurfaces;
13716         surfaces = model->data_surfaces;
13717
13718         bih = NULL;
13719         bih_triangles_count = -1;
13720         if(!dynamic)
13721         {
13722                 if(model->render_bih.numleafs)
13723                         bih = &model->render_bih;
13724                 else if(model->collision_bih.numleafs)
13725                         bih = &model->collision_bih;
13726         }
13727         if(bih)
13728                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13729         if(bih_triangles_count == 0)
13730                 return;
13731         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13732                 return;
13733         if(bih_triangles_count > 0)
13734         {
13735                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13736                 {
13737                         surfaceindex = bih_surfaces[triangleindex];
13738                         surface = surfaces + surfaceindex;
13739                         texture = surface->texture;
13740                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13741                                 continue;
13742                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13743                                 continue;
13744                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13745                 }
13746         }
13747         else
13748         {
13749                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13750                 {
13751                         surfaceindex = surfacelist[surfacelistindex];
13752                         surface = surfaces + surfaceindex;
13753                         // check cull box first because it rejects more than any other check
13754                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13755                                 continue;
13756                         // skip transparent surfaces
13757                         texture = surface->texture;
13758                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13759                                 continue;
13760                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13761                                 continue;
13762                         numtriangles = surface->num_triangles;
13763                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13764                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13765                 }
13766         }
13767 }
13768
13769 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13770 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)
13771 {
13772         int renderentityindex;
13773         float worldmins[3];
13774         float worldmaxs[3];
13775         entity_render_t *ent;
13776
13777         if (!cl_decals_newsystem.integer)
13778                 return;
13779
13780         worldmins[0] = worldorigin[0] - worldsize;
13781         worldmins[1] = worldorigin[1] - worldsize;
13782         worldmins[2] = worldorigin[2] - worldsize;
13783         worldmaxs[0] = worldorigin[0] + worldsize;
13784         worldmaxs[1] = worldorigin[1] + worldsize;
13785         worldmaxs[2] = worldorigin[2] + worldsize;
13786
13787         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13788
13789         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13790         {
13791                 ent = r_refdef.scene.entities[renderentityindex];
13792                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13793                         continue;
13794
13795                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13796         }
13797 }
13798
13799 typedef struct r_decalsystem_splatqueue_s
13800 {
13801         vec3_t worldorigin;
13802         vec3_t worldnormal;
13803         float color[4];
13804         float tcrange[4];
13805         float worldsize;
13806         int decalsequence;
13807 }
13808 r_decalsystem_splatqueue_t;
13809
13810 int r_decalsystem_numqueued = 0;
13811 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13812
13813 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)
13814 {
13815         r_decalsystem_splatqueue_t *queue;
13816
13817         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13818                 return;
13819
13820         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13821         VectorCopy(worldorigin, queue->worldorigin);
13822         VectorCopy(worldnormal, queue->worldnormal);
13823         Vector4Set(queue->color, r, g, b, a);
13824         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13825         queue->worldsize = worldsize;
13826         queue->decalsequence = cl.decalsequence++;
13827 }
13828
13829 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13830 {
13831         int i;
13832         r_decalsystem_splatqueue_t *queue;
13833
13834         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13835                 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);
13836         r_decalsystem_numqueued = 0;
13837 }
13838
13839 extern cvar_t cl_decals_max;
13840 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13841 {
13842         int i;
13843         decalsystem_t *decalsystem = &ent->decalsystem;
13844         int numdecals;
13845         int killsequence;
13846         tridecal_t *decal;
13847         float frametime;
13848         float lifetime;
13849
13850         if (!decalsystem->numdecals)
13851                 return;
13852
13853         if (r_showsurfaces.integer)
13854                 return;
13855
13856         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13857         {
13858                 R_DecalSystem_Reset(decalsystem);
13859                 return;
13860         }
13861
13862         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13863         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13864
13865         if (decalsystem->lastupdatetime)
13866                 frametime = (cl.time - decalsystem->lastupdatetime);
13867         else
13868                 frametime = 0;
13869         decalsystem->lastupdatetime = cl.time;
13870         decal = decalsystem->decals;
13871         numdecals = decalsystem->numdecals;
13872
13873         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13874         {
13875                 if (decal->color4ub[0][3])
13876                 {
13877                         decal->lived += frametime;
13878                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13879                         {
13880                                 memset(decal, 0, sizeof(*decal));
13881                                 if (decalsystem->freedecal > i)
13882                                         decalsystem->freedecal = i;
13883                         }
13884                 }
13885         }
13886         decal = decalsystem->decals;
13887         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13888                 numdecals--;
13889
13890         // collapse the array by shuffling the tail decals into the gaps
13891         for (;;)
13892         {
13893                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13894                         decalsystem->freedecal++;
13895                 if (decalsystem->freedecal == numdecals)
13896                         break;
13897                 decal[decalsystem->freedecal] = decal[--numdecals];
13898         }
13899
13900         decalsystem->numdecals = numdecals;
13901
13902         if (numdecals <= 0)
13903         {
13904                 // if there are no decals left, reset decalsystem
13905                 R_DecalSystem_Reset(decalsystem);
13906         }
13907 }
13908
13909 extern skinframe_t *decalskinframe;
13910 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13911 {
13912         int i;
13913         decalsystem_t *decalsystem = &ent->decalsystem;
13914         int numdecals;
13915         tridecal_t *decal;
13916         float faderate;
13917         float alpha;
13918         float *v3f;
13919         float *c4f;
13920         float *t2f;
13921         const int *e;
13922         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13923         int numtris = 0;
13924
13925         numdecals = decalsystem->numdecals;
13926         if (!numdecals)
13927                 return;
13928
13929         if (r_showsurfaces.integer)
13930                 return;
13931
13932         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13933         {
13934                 R_DecalSystem_Reset(decalsystem);
13935                 return;
13936         }
13937
13938         // if the model is static it doesn't matter what value we give for
13939         // wantnormals and wanttangents, so this logic uses only rules applicable
13940         // to a model, knowing that they are meaningless otherwise
13941         if (ent == r_refdef.scene.worldentity)
13942                 RSurf_ActiveWorldEntity();
13943         else
13944                 RSurf_ActiveModelEntity(ent, false, false, false);
13945
13946         decalsystem->lastupdatetime = cl.time;
13947         decal = decalsystem->decals;
13948
13949         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13950
13951         // update vertex positions for animated models
13952         v3f = decalsystem->vertex3f;
13953         c4f = decalsystem->color4f;
13954         t2f = decalsystem->texcoord2f;
13955         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13956         {
13957                 if (!decal->color4ub[0][3])
13958                         continue;
13959
13960                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13961                         continue;
13962
13963                 // update color values for fading decals
13964                 if (decal->lived >= cl_decals_time.value)
13965                 {
13966                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13967                         alpha *= (1.0f/255.0f);
13968                 }
13969                 else
13970                         alpha = 1.0f/255.0f;
13971
13972                 c4f[ 0] = decal->color4ub[0][0] * alpha;
13973                 c4f[ 1] = decal->color4ub[0][1] * alpha;
13974                 c4f[ 2] = decal->color4ub[0][2] * alpha;
13975                 c4f[ 3] = 1;
13976                 c4f[ 4] = decal->color4ub[1][0] * alpha;
13977                 c4f[ 5] = decal->color4ub[1][1] * alpha;
13978                 c4f[ 6] = decal->color4ub[1][2] * alpha;
13979                 c4f[ 7] = 1;
13980                 c4f[ 8] = decal->color4ub[2][0] * alpha;
13981                 c4f[ 9] = decal->color4ub[2][1] * alpha;
13982                 c4f[10] = decal->color4ub[2][2] * alpha;
13983                 c4f[11] = 1;
13984
13985                 t2f[0] = decal->texcoord2f[0][0];
13986                 t2f[1] = decal->texcoord2f[0][1];
13987                 t2f[2] = decal->texcoord2f[1][0];
13988                 t2f[3] = decal->texcoord2f[1][1];
13989                 t2f[4] = decal->texcoord2f[2][0];
13990                 t2f[5] = decal->texcoord2f[2][1];
13991
13992                 // update vertex positions for animated models
13993                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13994                 {
13995                         e = rsurface.modelelement3i + 3*decal->triangleindex;
13996                         VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
13997                         VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
13998                         VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
13999                 }
14000                 else
14001                 {
14002                         VectorCopy(decal->vertex3f[0], v3f);
14003                         VectorCopy(decal->vertex3f[1], v3f + 3);
14004                         VectorCopy(decal->vertex3f[2], v3f + 6);
14005                 }
14006
14007                 if (r_refdef.fogenabled)
14008                 {
14009                         alpha = RSurf_FogVertex(v3f);
14010                         VectorScale(c4f, alpha, c4f);
14011                         alpha = RSurf_FogVertex(v3f + 3);
14012                         VectorScale(c4f + 4, alpha, c4f + 4);
14013                         alpha = RSurf_FogVertex(v3f + 6);
14014                         VectorScale(c4f + 8, alpha, c4f + 8);
14015                 }
14016
14017                 v3f += 9;
14018                 c4f += 12;
14019                 t2f += 6;
14020                 numtris++;
14021         }
14022
14023         if (numtris > 0)
14024         {
14025                 r_refdef.stats.drawndecals += numtris;
14026
14027                 // now render the decals all at once
14028                 // (this assumes they all use one particle font texture!)
14029                 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);
14030                 R_Mesh_ResetTextureState();
14031                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
14032                 GL_DepthMask(false);
14033                 GL_DepthRange(0, 1);
14034                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
14035                 GL_DepthTest(true);
14036                 GL_CullFace(GL_NONE);
14037                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
14038                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
14039                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
14040         }
14041 }
14042
14043 static void R_DrawModelDecals(void)
14044 {
14045         int i, numdecals;
14046
14047         // fade faster when there are too many decals
14048         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14049         for (i = 0;i < r_refdef.scene.numentities;i++)
14050                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14051
14052         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
14053         for (i = 0;i < r_refdef.scene.numentities;i++)
14054                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14055                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14056
14057         R_DecalSystem_ApplySplatEntitiesQueue();
14058
14059         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14060         for (i = 0;i < r_refdef.scene.numentities;i++)
14061                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14062
14063         r_refdef.stats.totaldecals += numdecals;
14064
14065         if (r_showsurfaces.integer)
14066                 return;
14067
14068         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14069
14070         for (i = 0;i < r_refdef.scene.numentities;i++)
14071         {
14072                 if (!r_refdef.viewcache.entityvisible[i])
14073                         continue;
14074                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14075                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14076         }
14077 }
14078
14079 extern cvar_t mod_collision_bih;
14080 void R_DrawDebugModel(void)
14081 {
14082         entity_render_t *ent = rsurface.entity;
14083         int i, j, k, l, flagsmask;
14084         const msurface_t *surface;
14085         dp_model_t *model = ent->model;
14086         vec3_t v;
14087
14088         switch(vid.renderpath)
14089         {
14090         case RENDERPATH_GL11:
14091         case RENDERPATH_GL13:
14092         case RENDERPATH_GL20:
14093         case RENDERPATH_CGGL:
14094                 break;
14095         case RENDERPATH_D3D9:
14096                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14097                 return;
14098         case RENDERPATH_D3D10:
14099                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14100                 return;
14101         case RENDERPATH_D3D11:
14102                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14103                 return;
14104         }
14105
14106         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14107
14108         R_Mesh_ResetTextureState();
14109         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14110         GL_DepthRange(0, 1);
14111         GL_DepthTest(!r_showdisabledepthtest.integer);
14112         GL_DepthMask(false);
14113         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14114
14115         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14116         {
14117                 int triangleindex;
14118                 int bihleafindex;
14119                 qboolean cullbox = ent == r_refdef.scene.worldentity;
14120                 const q3mbrush_t *brush;
14121                 const bih_t *bih = &model->collision_bih;
14122                 const bih_leaf_t *bihleaf;
14123                 float vertex3f[3][3];
14124                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14125                 cullbox = false;
14126                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14127                 {
14128                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14129                                 continue;
14130                         switch (bihleaf->type)
14131                         {
14132                         case BIH_BRUSH:
14133                                 brush = model->brush.data_brushes + bihleaf->itemindex;
14134                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
14135                                 {
14136                                         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);
14137                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14138                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14139                                 }
14140                                 break;
14141                         case BIH_COLLISIONTRIANGLE:
14142                                 triangleindex = bihleaf->itemindex;
14143                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14144                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14145                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14146                                 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);
14147                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14148                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14149                                 break;
14150                         case BIH_RENDERTRIANGLE:
14151                                 triangleindex = bihleaf->itemindex;
14152                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14153                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14154                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14155                                 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);
14156                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14157                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14158                                 break;
14159                         }
14160                 }
14161         }
14162
14163         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14164
14165         if (r_showtris.integer || r_shownormals.integer)
14166         {
14167                 if (r_showdisabledepthtest.integer)
14168                 {
14169                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14170                         GL_DepthMask(false);
14171                 }
14172                 else
14173                 {
14174                         GL_BlendFunc(GL_ONE, GL_ZERO);
14175                         GL_DepthMask(true);
14176                 }
14177                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14178                 {
14179                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14180                                 continue;
14181                         rsurface.texture = R_GetCurrentTexture(surface->texture);
14182                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14183                         {
14184                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14185                                 if (r_showtris.value > 0)
14186                                 {
14187                                         if (!rsurface.texture->currentlayers->depthmask)
14188                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14189                                         else if (ent == r_refdef.scene.worldentity)
14190                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14191                                         else
14192                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14193                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14194                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14195                                         RSurf_DrawBatch();
14196                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14197                                         CHECKGLERROR
14198                                 }
14199                                 if (r_shownormals.value < 0)
14200                                 {
14201                                         qglBegin(GL_LINES);
14202                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14203                                         {
14204                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14205                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14206                                                 qglVertex3f(v[0], v[1], v[2]);
14207                                                 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14208                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14209                                                 qglVertex3f(v[0], v[1], v[2]);
14210                                         }
14211                                         qglEnd();
14212                                         CHECKGLERROR
14213                                 }
14214                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14215                                 {
14216                                         qglBegin(GL_LINES);
14217                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14218                                         {
14219                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14220                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14221                                                 qglVertex3f(v[0], v[1], v[2]);
14222                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14223                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14224                                                 qglVertex3f(v[0], v[1], v[2]);
14225                                         }
14226                                         qglEnd();
14227                                         CHECKGLERROR
14228                                         qglBegin(GL_LINES);
14229                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14230                                         {
14231                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14232                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14233                                                 qglVertex3f(v[0], v[1], v[2]);
14234                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14235                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14236                                                 qglVertex3f(v[0], v[1], v[2]);
14237                                         }
14238                                         qglEnd();
14239                                         CHECKGLERROR
14240                                         qglBegin(GL_LINES);
14241                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14242                                         {
14243                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14244                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14245                                                 qglVertex3f(v[0], v[1], v[2]);
14246                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14247                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14248                                                 qglVertex3f(v[0], v[1], v[2]);
14249                                         }
14250                                         qglEnd();
14251                                         CHECKGLERROR
14252                                 }
14253                         }
14254                 }
14255                 rsurface.texture = NULL;
14256         }
14257 }
14258
14259 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14260 int r_maxsurfacelist = 0;
14261 const msurface_t **r_surfacelist = NULL;
14262 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14263 {
14264         int i, j, endj, flagsmask;
14265         dp_model_t *model = r_refdef.scene.worldmodel;
14266         msurface_t *surfaces;
14267         unsigned char *update;
14268         int numsurfacelist = 0;
14269         if (model == NULL)
14270                 return;
14271
14272         if (r_maxsurfacelist < model->num_surfaces)
14273         {
14274                 r_maxsurfacelist = model->num_surfaces;
14275                 if (r_surfacelist)
14276                         Mem_Free((msurface_t**)r_surfacelist);
14277                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14278         }
14279
14280         RSurf_ActiveWorldEntity();
14281
14282         surfaces = model->data_surfaces;
14283         update = model->brushq1.lightmapupdateflags;
14284
14285         // update light styles on this submodel
14286         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14287         {
14288                 model_brush_lightstyleinfo_t *style;
14289                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14290                 {
14291                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14292                         {
14293                                 int *list = style->surfacelist;
14294                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14295                                 for (j = 0;j < style->numsurfaces;j++)
14296                                         update[list[j]] = true;
14297                         }
14298                 }
14299         }
14300
14301         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14302
14303         if (debug)
14304         {
14305                 R_DrawDebugModel();
14306                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14307                 return;
14308         }
14309
14310         rsurface.lightmaptexture = NULL;
14311         rsurface.deluxemaptexture = NULL;
14312         rsurface.uselightmaptexture = false;
14313         rsurface.texture = NULL;
14314         rsurface.rtlight = NULL;
14315         numsurfacelist = 0;
14316         // add visible surfaces to draw list
14317         for (i = 0;i < model->nummodelsurfaces;i++)
14318         {
14319                 j = model->sortedmodelsurfaces[i];
14320                 if (r_refdef.viewcache.world_surfacevisible[j])
14321                         r_surfacelist[numsurfacelist++] = surfaces + j;
14322         }
14323         // update lightmaps if needed
14324         if (model->brushq1.firstrender)
14325         {
14326                 model->brushq1.firstrender = false;
14327                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14328                         if (update[j])
14329                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14330         }
14331         else if (update)
14332         {
14333                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14334                         if (r_refdef.viewcache.world_surfacevisible[j])
14335                                 if (update[j])
14336                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14337         }
14338         // don't do anything if there were no surfaces
14339         if (!numsurfacelist)
14340         {
14341                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14342                 return;
14343         }
14344         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14345         GL_AlphaTest(false);
14346
14347         // add to stats if desired
14348         if (r_speeds.integer && !skysurfaces && !depthonly)
14349         {
14350                 r_refdef.stats.world_surfaces += numsurfacelist;
14351                 for (j = 0;j < numsurfacelist;j++)
14352                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14353         }
14354
14355         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14356 }
14357
14358 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14359 {
14360         int i, j, endj, flagsmask;
14361         dp_model_t *model = ent->model;
14362         msurface_t *surfaces;
14363         unsigned char *update;
14364         int numsurfacelist = 0;
14365         if (model == NULL)
14366                 return;
14367
14368         if (r_maxsurfacelist < model->num_surfaces)
14369         {
14370                 r_maxsurfacelist = model->num_surfaces;
14371                 if (r_surfacelist)
14372                         Mem_Free((msurface_t **)r_surfacelist);
14373                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14374         }
14375
14376         // if the model is static it doesn't matter what value we give for
14377         // wantnormals and wanttangents, so this logic uses only rules applicable
14378         // to a model, knowing that they are meaningless otherwise
14379         if (ent == r_refdef.scene.worldentity)
14380                 RSurf_ActiveWorldEntity();
14381         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14382                 RSurf_ActiveModelEntity(ent, false, false, false);
14383         else if (prepass)
14384                 RSurf_ActiveModelEntity(ent, true, true, true);
14385         else if (depthonly)
14386         {
14387                 switch (vid.renderpath)
14388                 {
14389                 case RENDERPATH_GL20:
14390                 case RENDERPATH_CGGL:
14391                 case RENDERPATH_D3D9:
14392                 case RENDERPATH_D3D10:
14393                 case RENDERPATH_D3D11:
14394                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14395                         break;
14396                 case RENDERPATH_GL13:
14397                 case RENDERPATH_GL11:
14398                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14399                         break;
14400                 }
14401         }
14402         else
14403         {
14404                 switch (vid.renderpath)
14405                 {
14406                 case RENDERPATH_GL20:
14407                 case RENDERPATH_CGGL:
14408                 case RENDERPATH_D3D9:
14409                 case RENDERPATH_D3D10:
14410                 case RENDERPATH_D3D11:
14411                         RSurf_ActiveModelEntity(ent, true, true, false);
14412                         break;
14413                 case RENDERPATH_GL13:
14414                 case RENDERPATH_GL11:
14415                         RSurf_ActiveModelEntity(ent, true, false, false);
14416                         break;
14417                 }
14418         }
14419
14420         surfaces = model->data_surfaces;
14421         update = model->brushq1.lightmapupdateflags;
14422
14423         // update light styles
14424         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14425         {
14426                 model_brush_lightstyleinfo_t *style;
14427                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14428                 {
14429                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14430                         {
14431                                 int *list = style->surfacelist;
14432                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14433                                 for (j = 0;j < style->numsurfaces;j++)
14434                                         update[list[j]] = true;
14435                         }
14436                 }
14437         }
14438
14439         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14440
14441         if (debug)
14442         {
14443                 R_DrawDebugModel();
14444                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14445                 return;
14446         }
14447
14448         rsurface.lightmaptexture = NULL;
14449         rsurface.deluxemaptexture = NULL;
14450         rsurface.uselightmaptexture = false;
14451         rsurface.texture = NULL;
14452         rsurface.rtlight = NULL;
14453         numsurfacelist = 0;
14454         // add visible surfaces to draw list
14455         for (i = 0;i < model->nummodelsurfaces;i++)
14456                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14457         // don't do anything if there were no surfaces
14458         if (!numsurfacelist)
14459         {
14460                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14461                 return;
14462         }
14463         // update lightmaps if needed
14464         if (update)
14465         {
14466                 int updated = 0;
14467                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14468                 {
14469                         if (update[j])
14470                         {
14471                                 updated++;
14472                                 R_BuildLightMap(ent, surfaces + j);
14473                         }
14474                 }
14475         }
14476         if (update)
14477                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14478                         if (update[j])
14479                                 R_BuildLightMap(ent, surfaces + j);
14480         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14481         GL_AlphaTest(false);
14482
14483         // add to stats if desired
14484         if (r_speeds.integer && !skysurfaces && !depthonly)
14485         {
14486                 r_refdef.stats.entities_surfaces += numsurfacelist;
14487                 for (j = 0;j < numsurfacelist;j++)
14488                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14489         }
14490
14491         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14492 }
14493
14494 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14495 {
14496         static texture_t texture;
14497         static msurface_t surface;
14498         const msurface_t *surfacelist = &surface;
14499
14500         // fake enough texture and surface state to render this geometry
14501
14502         texture.update_lastrenderframe = -1; // regenerate this texture
14503         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14504         texture.currentskinframe = skinframe;
14505         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14506         texture.offsetmapping = OFFSETMAPPING_OFF;
14507         texture.offsetscale = 1;
14508         texture.specularscalemod = 1;
14509         texture.specularpowermod = 1;
14510
14511         surface.texture = &texture;
14512         surface.num_triangles = numtriangles;
14513         surface.num_firsttriangle = firsttriangle;
14514         surface.num_vertices = numvertices;
14515         surface.num_firstvertex = firstvertex;
14516
14517         // now render it
14518         rsurface.texture = R_GetCurrentTexture(surface.texture);
14519         rsurface.lightmaptexture = NULL;
14520         rsurface.deluxemaptexture = NULL;
14521         rsurface.uselightmaptexture = false;
14522         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14523 }
14524
14525 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)
14526 {
14527         static msurface_t surface;
14528         const msurface_t *surfacelist = &surface;
14529
14530         // fake enough texture and surface state to render this geometry
14531
14532         surface.texture = texture;
14533         surface.num_triangles = numtriangles;
14534         surface.num_firsttriangle = firsttriangle;
14535         surface.num_vertices = numvertices;
14536         surface.num_firstvertex = firstvertex;
14537
14538         // now render it
14539         rsurface.texture = R_GetCurrentTexture(surface.texture);
14540         rsurface.lightmaptexture = NULL;
14541         rsurface.deluxemaptexture = NULL;
14542         rsurface.uselightmaptexture = false;
14543         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14544 }