]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
Added dp_waterscroll <scale> <speed> shader keyword as simple simulation of water...
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #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 // this called both on R_GLSL_CompileShader and R_HLSL_CacheShader
3588 // this function adds more "#define" to supply static parms, could be used by game-specific code part
3589 int vertstrings_count = 0;
3590 int geomstrings_count = 0;
3591 int fragstrings_count = 0;
3592 const char *vertstrings_list[64+3];
3593 const char *geomstrings_list[64+3];
3594 const char *fragstrings_list[64+3];
3595 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3596 {
3597         if (mode == SHADERMODE_POSTPROCESS && (permutation & SHADERPERMUTATION_SATURATION))
3598                 if (r_glsl_saturation_redcompensate.integer)
3599                         fragstrings_list[fragstrings_count++] = "#define SATURATION_REDCOMPENSATE\n";
3600 }
3601
3602 /// information about each possible shader permutation
3603 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3604 /// currently selected permutation
3605 r_glsl_permutation_t *r_glsl_permutation;
3606 /// storage for permutations linked in the hash table
3607 memexpandablearray_t r_glsl_permutationarray;
3608
3609 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3610 {
3611         //unsigned int hashdepth = 0;
3612         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3613         r_glsl_permutation_t *p;
3614         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3615         {
3616                 if (p->mode == mode && p->permutation == permutation)
3617                 {
3618                         //if (hashdepth > 10)
3619                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3620                         return p;
3621                 }
3622                 //hashdepth++;
3623         }
3624         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3625         p->mode = mode;
3626         p->permutation = permutation;
3627         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3628         r_glsl_permutationhash[mode][hashindex] = p;
3629         //if (hashdepth > 10)
3630         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3631         return p;
3632 }
3633
3634 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3635 {
3636         char *shaderstring;
3637         if (!filename || !filename[0])
3638                 return NULL;
3639         if (!strcmp(filename, "glsl/default.glsl"))
3640         {
3641                 if (!glslshaderstring)
3642                 {
3643                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3644                         if (glslshaderstring)
3645                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3646                         else
3647                                 glslshaderstring = (char *)builtinshaderstring;
3648                 }
3649                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3650                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3651                 return shaderstring;
3652         }
3653         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3654         if (shaderstring)
3655         {
3656                 if (printfromdisknotice)
3657                         Con_DPrintf("from disk %s... ", filename);
3658                 return shaderstring;
3659         }
3660         return shaderstring;
3661 }
3662
3663 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3664 {
3665         int i;
3666         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3667         char *vertexstring, *geometrystring, *fragmentstring;
3668         char permutationname[256];
3669
3670         if (p->compiled)
3671                 return;
3672         p->compiled = true;
3673         p->program = 0;
3674
3675         permutationname[0] = 0;
3676         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3677         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3678         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3679
3680         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3681
3682         // the first pretext is which type of shader to compile as
3683         // (later these will all be bound together as a program object)
3684         vertstrings_count = 0;
3685         geomstrings_count = 0;
3686         fragstrings_count = 0;
3687         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3688         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3689         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3690
3691         // the second pretext is the mode (for example a light source)
3692         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3693         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3694         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3695         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3696
3697         // now add all the permutation pretexts
3698         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3699         {
3700                 if (permutation & (1<<i))
3701                 {
3702                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3703                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3704                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3705                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3706                 }
3707                 else
3708                 {
3709                         // keep line numbers correct
3710                         vertstrings_list[vertstrings_count++] = "\n";
3711                         geomstrings_list[geomstrings_count++] = "\n";
3712                         fragstrings_list[fragstrings_count++] = "\n";
3713                 }
3714         }
3715
3716         // add static parms
3717         R_CompileShader_AddStaticParms(mode, permutation);
3718
3719         // now append the shader text itself
3720         vertstrings_list[vertstrings_count++] = vertexstring;
3721         geomstrings_list[geomstrings_count++] = geometrystring;
3722         fragstrings_list[fragstrings_count++] = fragmentstring;
3723
3724         // if any sources were NULL, clear the respective list
3725         if (!vertexstring)
3726                 vertstrings_count = 0;
3727         if (!geometrystring)
3728                 geomstrings_count = 0;
3729         if (!fragmentstring)
3730                 fragstrings_count = 0;
3731
3732         // compile the shader program
3733         if (vertstrings_count + geomstrings_count + fragstrings_count)
3734                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3735         if (p->program)
3736         {
3737                 CHECKGLERROR
3738                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3739                 // look up all the uniform variable names we care about, so we don't
3740                 // have to look them up every time we set them
3741
3742                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3743                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3744                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3745                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3746                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3747                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3748                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3749                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3750                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3751                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3752                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3753                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3754                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3755                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3756                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3757                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3758                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3759                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3760                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3761                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3762                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3763                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3764                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3765                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3766                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3767                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3768                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3769                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3770                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3771                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3772                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3773                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3774                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3775                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3776                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3777                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3778                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3779                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3780                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3781                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3782                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3783                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3784                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3785                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3786                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3787                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3788                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3789                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3790                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3791                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3792                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3793                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3794                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3795                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3796                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3797                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3798                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3799                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3800                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3801                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3802                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3803                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3804                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3805                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3806                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3807                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3808                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3809                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3810                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3811                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3812                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3813                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3814                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3815                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3816                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3817                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3818                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3819                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3820                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3821                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3822                 p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3823                 p->loc_NormalmapScrollBlend       = qglGetUniformLocationARB(p->program, "NormalmapScrollBlend");
3824                 // initialize the samplers to refer to the texture units we use
3825                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3826                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3827                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3828                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3829                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3830                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3831                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3832                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3833                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3834                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3835                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3836                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3837                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3838                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3839                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3840                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3841                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3842                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3843                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3844                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3845                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3846                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3847                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3848                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3849                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3850                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3851                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3852                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3853                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3854                 CHECKGLERROR
3855                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3856         }
3857         else
3858                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3859
3860         // free the strings
3861         if (vertexstring)
3862                 Mem_Free(vertexstring);
3863         if (geometrystring)
3864                 Mem_Free(geometrystring);
3865         if (fragmentstring)
3866                 Mem_Free(fragmentstring);
3867 }
3868
3869 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3870 {
3871         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3872         if (r_glsl_permutation != perm)
3873         {
3874                 r_glsl_permutation = perm;
3875                 if (!r_glsl_permutation->program)
3876                 {
3877                         if (!r_glsl_permutation->compiled)
3878                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3879                         if (!r_glsl_permutation->program)
3880                         {
3881                                 // remove features until we find a valid permutation
3882                                 int i;
3883                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3884                                 {
3885                                         // reduce i more quickly whenever it would not remove any bits
3886                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3887                                         if (!(permutation & j))
3888                                                 continue;
3889                                         permutation -= j;
3890                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3891                                         if (!r_glsl_permutation->compiled)
3892                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3893                                         if (r_glsl_permutation->program)
3894                                                 break;
3895                                 }
3896                                 if (i >= SHADERPERMUTATION_COUNT)
3897                                 {
3898                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3899                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3900                                         qglUseProgramObjectARB(0);CHECKGLERROR
3901                                         return; // no bit left to clear, entire mode is broken
3902                                 }
3903                         }
3904                 }
3905                 CHECKGLERROR
3906                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3907         }
3908         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3909         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3910         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3911 }
3912
3913 #ifdef SUPPORTCG
3914 #include <Cg/cgGL.h>
3915 struct r_cg_permutation_s;
3916 typedef struct r_cg_permutation_s
3917 {
3918         /// hash lookup data
3919         struct r_cg_permutation_s *hashnext;
3920         unsigned int mode;
3921         unsigned int permutation;
3922
3923         /// indicates if we have tried compiling this permutation already
3924         qboolean compiled;
3925         /// 0 if compilation failed
3926         CGprogram vprogram;
3927         CGprogram fprogram;
3928         /// locations of detected parameters in programs, or NULL if not found
3929         CGparameter vp_EyePosition;
3930         CGparameter vp_FogPlane;
3931         CGparameter vp_LightDir;
3932         CGparameter vp_LightPosition;
3933         CGparameter vp_ModelToLight;
3934         CGparameter vp_TexMatrix;
3935         CGparameter vp_BackgroundTexMatrix;
3936         CGparameter vp_ModelViewProjectionMatrix;
3937         CGparameter vp_ModelViewMatrix;
3938         CGparameter vp_ShadowMapMatrix;
3939
3940         CGparameter fp_Texture_First;
3941         CGparameter fp_Texture_Second;
3942         CGparameter fp_Texture_GammaRamps;
3943         CGparameter fp_Texture_Normal;
3944         CGparameter fp_Texture_Color;
3945         CGparameter fp_Texture_Gloss;
3946         CGparameter fp_Texture_Glow;
3947         CGparameter fp_Texture_SecondaryNormal;
3948         CGparameter fp_Texture_SecondaryColor;
3949         CGparameter fp_Texture_SecondaryGloss;
3950         CGparameter fp_Texture_SecondaryGlow;
3951         CGparameter fp_Texture_Pants;
3952         CGparameter fp_Texture_Shirt;
3953         CGparameter fp_Texture_FogHeightTexture;
3954         CGparameter fp_Texture_FogMask;
3955         CGparameter fp_Texture_Lightmap;
3956         CGparameter fp_Texture_Deluxemap;
3957         CGparameter fp_Texture_Attenuation;
3958         CGparameter fp_Texture_Cube;
3959         CGparameter fp_Texture_Refraction;
3960         CGparameter fp_Texture_Reflection;
3961         CGparameter fp_Texture_ShadowMap2D;
3962         CGparameter fp_Texture_CubeProjection;
3963         CGparameter fp_Texture_ScreenDepth;
3964         CGparameter fp_Texture_ScreenNormalMap;
3965         CGparameter fp_Texture_ScreenDiffuse;
3966         CGparameter fp_Texture_ScreenSpecular;
3967         CGparameter fp_Texture_ReflectMask;
3968         CGparameter fp_Texture_ReflectCube;
3969         CGparameter fp_Alpha;
3970         CGparameter fp_BloomBlur_Parameters;
3971         CGparameter fp_ClientTime;
3972         CGparameter fp_Color_Ambient;
3973         CGparameter fp_Color_Diffuse;
3974         CGparameter fp_Color_Specular;
3975         CGparameter fp_Color_Glow;
3976         CGparameter fp_Color_Pants;
3977         CGparameter fp_Color_Shirt;
3978         CGparameter fp_DeferredColor_Ambient;
3979         CGparameter fp_DeferredColor_Diffuse;
3980         CGparameter fp_DeferredColor_Specular;
3981         CGparameter fp_DeferredMod_Diffuse;
3982         CGparameter fp_DeferredMod_Specular;
3983         CGparameter fp_DistortScaleRefractReflect;
3984         CGparameter fp_EyePosition;
3985         CGparameter fp_FogColor;
3986         CGparameter fp_FogHeightFade;
3987         CGparameter fp_FogPlane;
3988         CGparameter fp_FogPlaneViewDist;
3989         CGparameter fp_FogRangeRecip;
3990         CGparameter fp_LightColor;
3991         CGparameter fp_LightDir;
3992         CGparameter fp_LightPosition;
3993         CGparameter fp_OffsetMapping_Scale;
3994         CGparameter fp_PixelSize;
3995         CGparameter fp_ReflectColor;
3996         CGparameter fp_ReflectFactor;
3997         CGparameter fp_ReflectOffset;
3998         CGparameter fp_RefractColor;
3999         CGparameter fp_Saturation;
4000         CGparameter fp_ScreenCenterRefractReflect;
4001         CGparameter fp_ScreenScaleRefractReflect;
4002         CGparameter fp_ScreenToDepth;
4003         CGparameter fp_ShadowMap_Parameters;
4004         CGparameter fp_ShadowMap_TextureScale;
4005         CGparameter fp_SpecularPower;
4006         CGparameter fp_UserVec1;
4007         CGparameter fp_UserVec2;
4008         CGparameter fp_UserVec3;
4009         CGparameter fp_UserVec4;
4010         CGparameter fp_ViewTintColor;
4011         CGparameter fp_ViewToLight;
4012         CGparameter fp_PixelToScreenTexCoord;
4013         CGparameter fp_ModelToReflectCube;
4014         CGparameter fp_BloomColorSubtract;
4015         CGparameter fp_NormalmapScrollBlend;
4016 }
4017 r_cg_permutation_t;
4018
4019 /// information about each possible shader permutation
4020 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4021 /// currently selected permutation
4022 r_cg_permutation_t *r_cg_permutation;
4023 /// storage for permutations linked in the hash table
4024 memexpandablearray_t r_cg_permutationarray;
4025
4026 #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));}}
4027
4028 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4029 {
4030         //unsigned int hashdepth = 0;
4031         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4032         r_cg_permutation_t *p;
4033         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4034         {
4035                 if (p->mode == mode && p->permutation == permutation)
4036                 {
4037                         //if (hashdepth > 10)
4038                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4039                         return p;
4040                 }
4041                 //hashdepth++;
4042         }
4043         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4044         p->mode = mode;
4045         p->permutation = permutation;
4046         p->hashnext = r_cg_permutationhash[mode][hashindex];
4047         r_cg_permutationhash[mode][hashindex] = p;
4048         //if (hashdepth > 10)
4049         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4050         return p;
4051 }
4052
4053 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4054 {
4055         char *shaderstring;
4056         if (!filename || !filename[0])
4057                 return NULL;
4058         if (!strcmp(filename, "cg/default.cg"))
4059         {
4060                 if (!cgshaderstring)
4061                 {
4062                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4063                         if (cgshaderstring)
4064                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4065                         else
4066                                 cgshaderstring = (char *)builtincgshaderstring;
4067                 }
4068                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4069                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4070                 return shaderstring;
4071         }
4072         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4073         if (shaderstring)
4074         {
4075                 if (printfromdisknotice)
4076                         Con_DPrintf("from disk %s... ", filename);
4077                 return shaderstring;
4078         }
4079         return shaderstring;
4080 }
4081
4082 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4083 {
4084         // TODO: load or create .fp and .vp shader files
4085 }
4086
4087 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4088 {
4089         int i;
4090         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4091         int vertstring_length = 0;
4092         int geomstring_length = 0;
4093         int fragstring_length = 0;
4094         char *t;
4095         char *vertexstring, *geometrystring, *fragmentstring;
4096         char *vertstring, *geomstring, *fragstring;
4097         char permutationname[256];
4098         char cachename[256];
4099         CGprofile vertexProfile;
4100         CGprofile fragmentProfile;
4101
4102         if (p->compiled)
4103                 return;
4104         p->compiled = true;
4105         p->vprogram = NULL;
4106         p->fprogram = NULL;
4107
4108         permutationname[0] = 0;
4109         cachename[0] = 0;
4110         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4111         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4112         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4113
4114         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4115         strlcat(cachename, "cg/", sizeof(cachename));
4116
4117         // the first pretext is which type of shader to compile as
4118         // (later these will all be bound together as a program object)
4119         vertstrings_count = 0;
4120         geomstrings_count = 0;
4121         fragstrings_count = 0;
4122         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4123         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4124         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4125
4126         // the second pretext is the mode (for example a light source)
4127         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4128         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4129         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4130         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4131         strlcat(cachename, modeinfo->name, sizeof(cachename));
4132
4133         // now add all the permutation pretexts
4134         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4135         {
4136                 if (permutation & (1<<i))
4137                 {
4138                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4139                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4140                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4141                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4142                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4143                 }
4144                 else
4145                 {
4146                         // keep line numbers correct
4147                         vertstrings_list[vertstrings_count++] = "\n";
4148                         geomstrings_list[geomstrings_count++] = "\n";
4149                         fragstrings_list[fragstrings_count++] = "\n";
4150                 }
4151         }
4152
4153         // add static parms
4154         R_CompileShader_AddStaticParms(mode, permutation);
4155
4156         // replace spaces in the cachename with _ characters
4157         for (i = 0;cachename[i];i++)
4158                 if (cachename[i] == ' ')
4159                         cachename[i] = '_';
4160
4161         // now append the shader text itself
4162         vertstrings_list[vertstrings_count++] = vertexstring;
4163         geomstrings_list[geomstrings_count++] = geometrystring;
4164         fragstrings_list[fragstrings_count++] = fragmentstring;
4165
4166         // if any sources were NULL, clear the respective list
4167         if (!vertexstring)
4168                 vertstrings_count = 0;
4169         if (!geometrystring)
4170                 geomstrings_count = 0;
4171         if (!fragmentstring)
4172                 fragstrings_count = 0;
4173
4174         vertstring_length = 0;
4175         for (i = 0;i < vertstrings_count;i++)
4176                 vertstring_length += strlen(vertstrings_list[i]);
4177         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4178         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4179                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4180
4181         geomstring_length = 0;
4182         for (i = 0;i < geomstrings_count;i++)
4183                 geomstring_length += strlen(geomstrings_list[i]);
4184         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4185         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4186                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4187
4188         fragstring_length = 0;
4189         for (i = 0;i < fragstrings_count;i++)
4190                 fragstring_length += strlen(fragstrings_list[i]);
4191         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4192         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4193                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4194
4195         CHECKGLERROR
4196         CHECKCGERROR
4197         //vertexProfile = CG_PROFILE_ARBVP1;
4198         //fragmentProfile = CG_PROFILE_ARBFP1;
4199         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4200         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4201         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4202         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4203         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4204         CHECKGLERROR
4205
4206         // try to load the cached shader, or generate one
4207         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4208
4209         // if caching failed, do a dynamic compile for now
4210         CHECKCGERROR
4211         if (vertstring[0] && !p->vprogram)
4212                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4213         CHECKCGERROR
4214         if (fragstring[0] && !p->fprogram)
4215                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4216         CHECKCGERROR
4217
4218         // look up all the uniform variable names we care about, so we don't
4219         // have to look them up every time we set them
4220         if (p->vprogram)
4221         {
4222                 CHECKCGERROR
4223                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4224                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4225                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4226                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4227                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4228                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4229                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4230                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4231                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4232                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4233                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4234                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4235                 CHECKCGERROR
4236         }
4237         if (p->fprogram)
4238         {
4239                 CHECKCGERROR
4240                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4241                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4242                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4243                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4244                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4245                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4246                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4247                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4248                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4249                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4250                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4251                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4252                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4253                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4254                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4255                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4256                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4257                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4258                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4259                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4260                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4261                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4262                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4263                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4264                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4265                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4266                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4267                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4268                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4269                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4270                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4271                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4272                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4273                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4274                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4275                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4276                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4277                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4278                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4279                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4280                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4281                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4282                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4283                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4284                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4285                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4286                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4287                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4288                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4289                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4290                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4291                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4292                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4293                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4294                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4295                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4296                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4297                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4298                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4299                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4300                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4301                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4302                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4303                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4304                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4305                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4306                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4307                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4308                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4309                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4310                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4311                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4312                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4313                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4314                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4315                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4316                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4317                 p->fp_NormalmapScrollBlend       = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4318                 CHECKCGERROR
4319         }
4320
4321         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4322                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4323         else
4324                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4325
4326         // free the strings
4327         if (vertstring)
4328                 Mem_Free(vertstring);
4329         if (geomstring)
4330                 Mem_Free(geomstring);
4331         if (fragstring)
4332                 Mem_Free(fragstring);
4333         if (vertexstring)
4334                 Mem_Free(vertexstring);
4335         if (geometrystring)
4336                 Mem_Free(geometrystring);
4337         if (fragmentstring)
4338                 Mem_Free(fragmentstring);
4339 }
4340
4341 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4342 {
4343         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4344         CHECKGLERROR
4345         CHECKCGERROR
4346         if (r_cg_permutation != perm)
4347         {
4348                 r_cg_permutation = perm;
4349                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4350                 {
4351                         if (!r_cg_permutation->compiled)
4352                                 R_CG_CompilePermutation(perm, mode, permutation);
4353                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4354                         {
4355                                 // remove features until we find a valid permutation
4356                                 int i;
4357                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4358                                 {
4359                                         // reduce i more quickly whenever it would not remove any bits
4360                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4361                                         if (!(permutation & j))
4362                                                 continue;
4363                                         permutation -= j;
4364                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4365                                         if (!r_cg_permutation->compiled)
4366                                                 R_CG_CompilePermutation(perm, mode, permutation);
4367                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4368                                                 break;
4369                                 }
4370                                 if (i >= SHADERPERMUTATION_COUNT)
4371                                 {
4372                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4373                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4374                                         return; // no bit left to clear, entire mode is broken
4375                                 }
4376                         }
4377                 }
4378                 CHECKGLERROR
4379                 CHECKCGERROR
4380                 if (r_cg_permutation->vprogram)
4381                 {
4382                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4383                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4384                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4385                 }
4386                 else
4387                 {
4388                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4389                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4390                 }
4391                 if (r_cg_permutation->fprogram)
4392                 {
4393                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4394                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4395                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4396                 }
4397                 else
4398                 {
4399                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4400                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4401                 }
4402         }
4403         CHECKCGERROR
4404         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4405         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4406         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4407 }
4408
4409 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4410 {
4411         cgGLSetTextureParameter(param, R_GetTexture(tex));
4412         cgGLEnableTextureParameter(param);
4413 }
4414 #endif
4415
4416 #ifdef SUPPORTD3D
4417
4418 #ifdef SUPPORTD3D
4419 #include <d3d9.h>
4420 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4421 extern D3DCAPS9 vid_d3d9caps;
4422 #endif
4423
4424 struct r_hlsl_permutation_s;
4425 typedef struct r_hlsl_permutation_s
4426 {
4427         /// hash lookup data
4428         struct r_hlsl_permutation_s *hashnext;
4429         unsigned int mode;
4430         unsigned int permutation;
4431
4432         /// indicates if we have tried compiling this permutation already
4433         qboolean compiled;
4434         /// NULL if compilation failed
4435         IDirect3DVertexShader9 *vertexshader;
4436         IDirect3DPixelShader9 *pixelshader;
4437 }
4438 r_hlsl_permutation_t;
4439
4440 typedef enum D3DVSREGISTER_e
4441 {
4442         D3DVSREGISTER_TexMatrix = 0, // float4x4
4443         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4444         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4445         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4446         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4447         D3DVSREGISTER_ModelToLight = 20, // float4x4
4448         D3DVSREGISTER_EyePosition = 24,
4449         D3DVSREGISTER_FogPlane = 25,
4450         D3DVSREGISTER_LightDir = 26,
4451         D3DVSREGISTER_LightPosition = 27,
4452 }
4453 D3DVSREGISTER_t;
4454
4455 typedef enum D3DPSREGISTER_e
4456 {
4457         D3DPSREGISTER_Alpha = 0,
4458         D3DPSREGISTER_BloomBlur_Parameters = 1,
4459         D3DPSREGISTER_ClientTime = 2,
4460         D3DPSREGISTER_Color_Ambient = 3,
4461         D3DPSREGISTER_Color_Diffuse = 4,
4462         D3DPSREGISTER_Color_Specular = 5,
4463         D3DPSREGISTER_Color_Glow = 6,
4464         D3DPSREGISTER_Color_Pants = 7,
4465         D3DPSREGISTER_Color_Shirt = 8,
4466         D3DPSREGISTER_DeferredColor_Ambient = 9,
4467         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4468         D3DPSREGISTER_DeferredColor_Specular = 11,
4469         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4470         D3DPSREGISTER_DeferredMod_Specular = 13,
4471         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4472         D3DPSREGISTER_EyePosition = 15, // unused
4473         D3DPSREGISTER_FogColor = 16,
4474         D3DPSREGISTER_FogHeightFade = 17,
4475         D3DPSREGISTER_FogPlane = 18,
4476         D3DPSREGISTER_FogPlaneViewDist = 19,
4477         D3DPSREGISTER_FogRangeRecip = 20,
4478         D3DPSREGISTER_LightColor = 21,
4479         D3DPSREGISTER_LightDir = 22, // unused
4480         D3DPSREGISTER_LightPosition = 23,
4481         D3DPSREGISTER_OffsetMapping_Scale = 24,
4482         D3DPSREGISTER_PixelSize = 25,
4483         D3DPSREGISTER_ReflectColor = 26,
4484         D3DPSREGISTER_ReflectFactor = 27,
4485         D3DPSREGISTER_ReflectOffset = 28,
4486         D3DPSREGISTER_RefractColor = 29,
4487         D3DPSREGISTER_Saturation = 30,
4488         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4489         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4490         D3DPSREGISTER_ScreenToDepth = 33,
4491         D3DPSREGISTER_ShadowMap_Parameters = 34,
4492         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4493         D3DPSREGISTER_SpecularPower = 36,
4494         D3DPSREGISTER_UserVec1 = 37,
4495         D3DPSREGISTER_UserVec2 = 38,
4496         D3DPSREGISTER_UserVec3 = 39,
4497         D3DPSREGISTER_UserVec4 = 40,
4498         D3DPSREGISTER_ViewTintColor = 41,
4499         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4500         D3DPSREGISTER_BloomColorSubtract = 43,
4501         D3DPSREGISTER_ViewToLight = 44, // float4x4
4502         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4503         D3DPSREGISTER_NormalmapScrollBlend = 52,
4504         // next at 53
4505 }
4506 D3DPSREGISTER_t;
4507
4508 /// information about each possible shader permutation
4509 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4510 /// currently selected permutation
4511 r_hlsl_permutation_t *r_hlsl_permutation;
4512 /// storage for permutations linked in the hash table
4513 memexpandablearray_t r_hlsl_permutationarray;
4514
4515 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4516 {
4517         //unsigned int hashdepth = 0;
4518         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4519         r_hlsl_permutation_t *p;
4520         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4521         {
4522                 if (p->mode == mode && p->permutation == permutation)
4523                 {
4524                         //if (hashdepth > 10)
4525                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4526                         return p;
4527                 }
4528                 //hashdepth++;
4529         }
4530         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4531         p->mode = mode;
4532         p->permutation = permutation;
4533         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4534         r_hlsl_permutationhash[mode][hashindex] = p;
4535         //if (hashdepth > 10)
4536         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4537         return p;
4538 }
4539
4540 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4541 {
4542         char *shaderstring;
4543         if (!filename || !filename[0])
4544                 return NULL;
4545         if (!strcmp(filename, "hlsl/default.hlsl"))
4546         {
4547                 if (!hlslshaderstring)
4548                 {
4549                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4550                         if (hlslshaderstring)
4551                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4552                         else
4553                                 hlslshaderstring = (char *)builtincgshaderstring;
4554                 }
4555                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4556                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4557                 return shaderstring;
4558         }
4559         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4560         if (shaderstring)
4561         {
4562                 if (printfromdisknotice)
4563                         Con_DPrintf("from disk %s... ", filename);
4564                 return shaderstring;
4565         }
4566         return shaderstring;
4567 }
4568
4569 #include <d3dx9.h>
4570 //#include <d3dx9shader.h>
4571 //#include <d3dx9mesh.h>
4572
4573 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4574 {
4575         DWORD *vsbin = NULL;
4576         DWORD *psbin = NULL;
4577         fs_offset_t vsbinsize;
4578         fs_offset_t psbinsize;
4579 //      IDirect3DVertexShader9 *vs = NULL;
4580 //      IDirect3DPixelShader9 *ps = NULL;
4581         ID3DXBuffer *vslog = NULL;
4582         ID3DXBuffer *vsbuffer = NULL;
4583         ID3DXConstantTable *vsconstanttable = NULL;
4584         ID3DXBuffer *pslog = NULL;
4585         ID3DXBuffer *psbuffer = NULL;
4586         ID3DXConstantTable *psconstanttable = NULL;
4587         int vsresult = 0;
4588         int psresult = 0;
4589         char temp[MAX_INPUTLINE];
4590         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4591         qboolean debugshader = gl_paranoid.integer != 0;
4592         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4593         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4594         if (!debugshader)
4595         {
4596                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4597                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4598         }
4599         if ((!vsbin && vertstring) || (!psbin && fragstring))
4600         {
4601                 const char* dllnames_d3dx9 [] =
4602                 {
4603                         "d3dx9_43.dll",
4604                         "d3dx9_42.dll",
4605                         "d3dx9_41.dll",
4606                         "d3dx9_40.dll",
4607                         "d3dx9_39.dll",
4608                         "d3dx9_38.dll",
4609                         "d3dx9_37.dll",
4610                         "d3dx9_36.dll",
4611                         "d3dx9_35.dll",
4612                         "d3dx9_34.dll",
4613                         "d3dx9_33.dll",
4614                         "d3dx9_32.dll",
4615                         "d3dx9_31.dll",
4616                         "d3dx9_30.dll",
4617                         "d3dx9_29.dll",
4618                         "d3dx9_28.dll",
4619                         "d3dx9_27.dll",
4620                         "d3dx9_26.dll",
4621                         "d3dx9_25.dll",
4622                         "d3dx9_24.dll",
4623                         NULL
4624                 };
4625                 dllhandle_t d3dx9_dll = NULL;
4626                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4627                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4628                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4629                 dllfunction_t d3dx9_dllfuncs[] =
4630                 {
4631                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4632                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4633                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4634                         {NULL, NULL}
4635                 };
4636                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4637                 {
4638                         DWORD shaderflags = 0;
4639                         if (debugshader)
4640                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4641                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4642                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4643                         if (vertstring && vertstring[0])
4644                         {
4645                                 if (debugshader)
4646                                 {
4647 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4648 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4649                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4650                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4651                                 }
4652                                 else
4653                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4654                                 if (vsbuffer)
4655                                 {
4656                                         vsbinsize = vsbuffer->GetBufferSize();
4657                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4658                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4659                                         vsbuffer->Release();
4660                                 }
4661                                 if (vslog)
4662                                 {
4663                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4664                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4665                                         vslog->Release();
4666                                 }
4667                         }
4668                         if (fragstring && fragstring[0])
4669                         {
4670                                 if (debugshader)
4671                                 {
4672 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4673 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4674                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4675                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4676                                 }
4677                                 else
4678                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4679                                 if (psbuffer)
4680                                 {
4681                                         psbinsize = psbuffer->GetBufferSize();
4682                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4683                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4684                                         psbuffer->Release();
4685                                 }
4686                                 if (pslog)
4687                                 {
4688                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4689                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4690                                         pslog->Release();
4691                                 }
4692                         }
4693                         Sys_UnloadLibrary(&d3dx9_dll);
4694                 }
4695                 else
4696                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4697         }
4698         if (vsbin && psbin)
4699         {
4700                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4701                 if (FAILED(vsresult))
4702                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4703                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4704                 if (FAILED(psresult))
4705                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4706         }
4707         // free the shader data
4708         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4709         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4710 }
4711
4712 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4713 {
4714         int i;
4715         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4716         int vertstring_length = 0;
4717         int geomstring_length = 0;
4718         int fragstring_length = 0;
4719         char *t;
4720         char *vertexstring, *geometrystring, *fragmentstring;
4721         char *vertstring, *geomstring, *fragstring;
4722         char permutationname[256];
4723         char cachename[256];
4724
4725         if (p->compiled)
4726                 return;
4727         p->compiled = true;
4728         p->vertexshader = NULL;
4729         p->pixelshader = NULL;
4730
4731         permutationname[0] = 0;
4732         cachename[0] = 0;
4733         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4734         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4735         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4736
4737         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4738         strlcat(cachename, "hlsl/", sizeof(cachename));
4739
4740         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4741         vertstrings_count = 0;
4742         geomstrings_count = 0;
4743         fragstrings_count = 0;
4744         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4745         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4746         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4747
4748         // the first pretext is which type of shader to compile as
4749         // (later these will all be bound together as a program object)
4750         vertstrings_count = 0;
4751         geomstrings_count = 0;
4752         fragstrings_count = 0;
4753         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4754         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4755         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4756
4757         // the second pretext is the mode (for example a light source)
4758         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4759         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4760         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4761         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4762         strlcat(cachename, modeinfo->name, sizeof(cachename));
4763
4764         // now add all the permutation pretexts
4765         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4766         {
4767                 if (permutation & (1<<i))
4768                 {
4769                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4770                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4771                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4772                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4773                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4774                 }
4775                 else
4776                 {
4777                         // keep line numbers correct
4778                         vertstrings_list[vertstrings_count++] = "\n";
4779                         geomstrings_list[geomstrings_count++] = "\n";
4780                         fragstrings_list[fragstrings_count++] = "\n";
4781                 }
4782         }
4783
4784         // add static parms
4785         R_CompileShader_AddStaticParms(mode, permutation);
4786
4787         // replace spaces in the cachename with _ characters
4788         for (i = 0;cachename[i];i++)
4789                 if (cachename[i] == ' ')
4790                         cachename[i] = '_';
4791
4792         // now append the shader text itself
4793         vertstrings_list[vertstrings_count++] = vertexstring;
4794         geomstrings_list[geomstrings_count++] = geometrystring;
4795         fragstrings_list[fragstrings_count++] = fragmentstring;
4796
4797         // if any sources were NULL, clear the respective list
4798         if (!vertexstring)
4799                 vertstrings_count = 0;
4800         if (!geometrystring)
4801                 geomstrings_count = 0;
4802         if (!fragmentstring)
4803                 fragstrings_count = 0;
4804
4805         vertstring_length = 0;
4806         for (i = 0;i < vertstrings_count;i++)
4807                 vertstring_length += strlen(vertstrings_list[i]);
4808         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4809         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4810                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4811
4812         geomstring_length = 0;
4813         for (i = 0;i < geomstrings_count;i++)
4814                 geomstring_length += strlen(geomstrings_list[i]);
4815         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4816         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4817                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4818
4819         fragstring_length = 0;
4820         for (i = 0;i < fragstrings_count;i++)
4821                 fragstring_length += strlen(fragstrings_list[i]);
4822         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4823         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4824                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4825
4826         // try to load the cached shader, or generate one
4827         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4828
4829         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4830                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4831         else
4832                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4833
4834         // free the strings
4835         if (vertstring)
4836                 Mem_Free(vertstring);
4837         if (geomstring)
4838                 Mem_Free(geomstring);
4839         if (fragstring)
4840                 Mem_Free(fragstring);
4841         if (vertexstring)
4842                 Mem_Free(vertexstring);
4843         if (geometrystring)
4844                 Mem_Free(geometrystring);
4845         if (fragmentstring)
4846                 Mem_Free(fragmentstring);
4847 }
4848
4849 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4850 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4851 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);}
4852 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);}
4853 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);}
4854 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);}
4855
4856 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4857 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4858 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);}
4859 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);}
4860 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);}
4861 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);}
4862
4863 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4864 {
4865         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4866         if (r_hlsl_permutation != perm)
4867         {
4868                 r_hlsl_permutation = perm;
4869                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4870                 {
4871                         if (!r_hlsl_permutation->compiled)
4872                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4873                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4874                         {
4875                                 // remove features until we find a valid permutation
4876                                 int i;
4877                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4878                                 {
4879                                         // reduce i more quickly whenever it would not remove any bits
4880                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4881                                         if (!(permutation & j))
4882                                                 continue;
4883                                         permutation -= j;
4884                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4885                                         if (!r_hlsl_permutation->compiled)
4886                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4887                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4888                                                 break;
4889                                 }
4890                                 if (i >= SHADERPERMUTATION_COUNT)
4891                                 {
4892                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4893                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4894                                         return; // no bit left to clear, entire mode is broken
4895                                 }
4896                         }
4897                 }
4898                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4899                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4900         }
4901         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4902         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4903         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4904 }
4905 #endif
4906
4907 void R_GLSL_Restart_f(void)
4908 {
4909         unsigned int i, limit;
4910         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4911                 Mem_Free(glslshaderstring);
4912         glslshaderstring = NULL;
4913         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4914                 Mem_Free(cgshaderstring);
4915         cgshaderstring = NULL;
4916         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4917                 Mem_Free(hlslshaderstring);
4918         hlslshaderstring = NULL;
4919         switch(vid.renderpath)
4920         {
4921         case RENDERPATH_D3D9:
4922 #ifdef SUPPORTD3D
4923                 {
4924                         r_hlsl_permutation_t *p;
4925                         r_hlsl_permutation = NULL;
4926 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4927 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4928 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4929 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4930                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4931                         for (i = 0;i < limit;i++)
4932                         {
4933                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4934                                 {
4935                                         if (p->vertexshader)
4936                                                 IDirect3DVertexShader9_Release(p->vertexshader);
4937                                         if (p->pixelshader)
4938                                                 IDirect3DPixelShader9_Release(p->pixelshader);
4939                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4940                                 }
4941                         }
4942                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4943                 }
4944 #endif
4945                 break;
4946         case RENDERPATH_D3D10:
4947                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4948                 break;
4949         case RENDERPATH_D3D11:
4950                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4951                 break;
4952         case RENDERPATH_GL20:
4953                 {
4954                         r_glsl_permutation_t *p;
4955                         r_glsl_permutation = NULL;
4956                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4957                         for (i = 0;i < limit;i++)
4958                         {
4959                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4960                                 {
4961                                         GL_Backend_FreeProgram(p->program);
4962                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4963                                 }
4964                         }
4965                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4966                 }
4967                 break;
4968         case RENDERPATH_CGGL:
4969 #ifdef SUPPORTCG
4970                 {
4971                         r_cg_permutation_t *p;
4972                         r_cg_permutation = NULL;
4973                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4974                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4975                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4976                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4977                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4978                         for (i = 0;i < limit;i++)
4979                         {
4980                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4981                                 {
4982                                         if (p->vprogram)
4983                                                 cgDestroyProgram(p->vprogram);
4984                                         if (p->fprogram)
4985                                                 cgDestroyProgram(p->fprogram);
4986                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4987                                 }
4988                         }
4989                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4990                 }
4991 #endif
4992                 break;
4993         case RENDERPATH_GL13:
4994         case RENDERPATH_GL11:
4995                 break;
4996         }
4997 }
4998
4999 void R_GLSL_DumpShader_f(void)
5000 {
5001         int i;
5002         qfile_t *file;
5003
5004         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5005         if (file)
5006         {
5007                 FS_Print(file, "/* The engine may define the following macros:\n");
5008                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5009                 for (i = 0;i < SHADERMODE_COUNT;i++)
5010                         FS_Print(file, glslshadermodeinfo[i].pretext);
5011                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5012                         FS_Print(file, shaderpermutationinfo[i].pretext);
5013                 FS_Print(file, "*/\n");
5014                 FS_Print(file, builtinshaderstring);
5015                 FS_Close(file);
5016                 Con_Printf("glsl/default.glsl written\n");
5017         }
5018         else
5019                 Con_Printf("failed to write to glsl/default.glsl\n");
5020
5021 #ifdef SUPPORTCG
5022         file = FS_OpenRealFile("cg/default.cg", "w", false);
5023         if (file)
5024         {
5025                 FS_Print(file, "/* The engine may define the following macros:\n");
5026                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5027                 for (i = 0;i < SHADERMODE_COUNT;i++)
5028                         FS_Print(file, cgshadermodeinfo[i].pretext);
5029                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5030                         FS_Print(file, shaderpermutationinfo[i].pretext);
5031                 FS_Print(file, "*/\n");
5032                 FS_Print(file, builtincgshaderstring);
5033                 FS_Close(file);
5034                 Con_Printf("cg/default.cg written\n");
5035         }
5036         else
5037                 Con_Printf("failed to write to cg/default.cg\n");
5038 #endif
5039
5040 #ifdef SUPPORTD3D
5041         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5042         if (file)
5043         {
5044                 FS_Print(file, "/* The engine may define the following macros:\n");
5045                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5046                 for (i = 0;i < SHADERMODE_COUNT;i++)
5047                         FS_Print(file, hlslshadermodeinfo[i].pretext);
5048                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5049                         FS_Print(file, shaderpermutationinfo[i].pretext);
5050                 FS_Print(file, "*/\n");
5051                 FS_Print(file, builtincgshaderstring);
5052                 FS_Close(file);
5053                 Con_Printf("hlsl/default.hlsl written\n");
5054         }
5055         else
5056                 Con_Printf("failed to write to hlsl/default.hlsl\n");
5057 #endif
5058 }
5059
5060 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5061 {
5062         if (!second)
5063                 texturemode = GL_MODULATE;
5064         switch (vid.renderpath)
5065         {
5066         case RENDERPATH_D3D9:
5067 #ifdef SUPPORTD3D
5068                 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))));
5069                 R_Mesh_TexBind(GL20TU_FIRST , first );
5070                 R_Mesh_TexBind(GL20TU_SECOND, second);
5071 #endif
5072                 break;
5073         case RENDERPATH_D3D10:
5074                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5075                 break;
5076         case RENDERPATH_D3D11:
5077                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5078                 break;
5079         case RENDERPATH_GL20:
5080                 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))));
5081                 R_Mesh_TexBind(GL20TU_FIRST , first );
5082                 R_Mesh_TexBind(GL20TU_SECOND, second);
5083                 break;
5084         case RENDERPATH_CGGL:
5085 #ifdef SUPPORTCG
5086                 CHECKCGERROR
5087                 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))));
5088                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5089                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5090 #endif
5091                 break;
5092         case RENDERPATH_GL13:
5093                 R_Mesh_TexBind(0, first );
5094                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5095                 R_Mesh_TexBind(1, second);
5096                 if (second)
5097                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5098                 break;
5099         case RENDERPATH_GL11:
5100                 R_Mesh_TexBind(0, first );
5101                 break;
5102         }
5103 }
5104
5105 void R_SetupShader_DepthOrShadow(void)
5106 {
5107         switch (vid.renderpath)
5108         {
5109         case RENDERPATH_D3D9:
5110 #ifdef SUPPORTD3D
5111                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5112 #endif
5113                 break;
5114         case RENDERPATH_D3D10:
5115                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5116                 break;
5117         case RENDERPATH_D3D11:
5118                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5119                 break;
5120         case RENDERPATH_GL20:
5121                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5122                 break;
5123         case RENDERPATH_CGGL:
5124 #ifdef SUPPORTCG
5125                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5126 #endif
5127                 break;
5128         case RENDERPATH_GL13:
5129                 R_Mesh_TexBind(0, 0);
5130                 R_Mesh_TexBind(1, 0);
5131                 break;
5132         case RENDERPATH_GL11:
5133                 R_Mesh_TexBind(0, 0);
5134                 break;
5135         }
5136 }
5137
5138 void R_SetupShader_ShowDepth(void)
5139 {
5140         switch (vid.renderpath)
5141         {
5142         case RENDERPATH_D3D9:
5143 #ifdef SUPPORTHLSL
5144                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5145 #endif
5146                 break;
5147         case RENDERPATH_D3D10:
5148                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5149                 break;
5150         case RENDERPATH_D3D11:
5151                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5152                 break;
5153         case RENDERPATH_GL20:
5154                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5155                 break;
5156         case RENDERPATH_CGGL:
5157 #ifdef SUPPORTCG
5158                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5159 #endif
5160                 break;
5161         case RENDERPATH_GL13:
5162                 break;
5163         case RENDERPATH_GL11:
5164                 break;
5165         }
5166 }
5167
5168 extern qboolean r_shadow_usingdeferredprepass;
5169 extern cvar_t r_shadow_deferred_8bitrange;
5170 extern rtexture_t *r_shadow_attenuationgradienttexture;
5171 extern rtexture_t *r_shadow_attenuation2dtexture;
5172 extern rtexture_t *r_shadow_attenuation3dtexture;
5173 extern qboolean r_shadow_usingshadowmap2d;
5174 extern qboolean r_shadow_usingshadowmaportho;
5175 extern float r_shadow_shadowmap_texturescale[2];
5176 extern float r_shadow_shadowmap_parameters[4];
5177 extern qboolean r_shadow_shadowmapvsdct;
5178 extern qboolean r_shadow_shadowmapsampler;
5179 extern int r_shadow_shadowmappcf;
5180 extern rtexture_t *r_shadow_shadowmap2dtexture;
5181 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5182 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5183 extern matrix4x4_t r_shadow_shadowmapmatrix;
5184 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5185 extern int r_shadow_prepass_width;
5186 extern int r_shadow_prepass_height;
5187 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5188 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5189 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5190 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5191 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5192 extern cvar_t gl_mesh_separatearrays;
5193 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5194 {
5195         // a blendfunc allows colormod if:
5196         // a) it can never keep the destination pixel invariant, or
5197         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5198         // this is to prevent unintended side effects from colormod
5199
5200         // in formulas:
5201         // IF there is a (s, sa) for which for all (d, da),
5202         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5203         // THEN, for this (s, sa) and all (colormod, d, da):
5204         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5205         // OBVIOUSLY, this means that
5206         //   s*colormod * src(s*colormod, d, sa, da) = 0
5207         //   dst(s*colormod, d, sa, da)              = 1
5208
5209         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5210
5211         // main condition to leave dst color invariant:
5212         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5213         //   src == GL_ZERO:
5214         //     s * 0 + d * dst(s, d, sa, da) == d
5215         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5216         //       => colormod is a problem for GL_SRC_COLOR only
5217         //   src == GL_ONE:
5218         //     s + d * dst(s, d, sa, da) == d
5219         //       => s == 0
5220         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5221         //       => colormod is never problematic for these
5222         //   src == GL_SRC_COLOR:
5223         //     s*s + d * dst(s, d, sa, da) == d
5224         //       => s == 0
5225         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5226         //       => colormod is never problematic for these
5227         //   src == GL_ONE_MINUS_SRC_COLOR:
5228         //     s*(1-s) + d * dst(s, d, sa, da) == d
5229         //       => s == 0 or s == 1
5230         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5231         //       => colormod is a problem for GL_SRC_COLOR only
5232         //   src == GL_DST_COLOR
5233         //     s*d + d * dst(s, d, sa, da) == d
5234         //       => s == 1
5235         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5236         //       => colormod is always a problem
5237         //     or
5238         //       => s == 0
5239         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5240         //       => colormod is never problematic for these
5241         //       => BUT, we do not know s! We must assume it is problematic
5242         //       then... except in GL_ONE case, where we know all invariant
5243         //       cases are fine
5244         //   src == GL_ONE_MINUS_DST_COLOR
5245         //     s*(1-d) + d * dst(s, d, sa, da) == d
5246         //       => s == 0 (1-d is impossible to handle for our desired result)
5247         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5248         //       => colormod is never problematic for these
5249         //   src == GL_SRC_ALPHA
5250         //     s*sa + d * dst(s, d, sa, da) == d
5251         //       => s == 0, or sa == 0
5252         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5253         //       => colormod breaks in the case GL_SRC_COLOR only
5254         //   src == GL_ONE_MINUS_SRC_ALPHA
5255         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5256         //       => s == 0, or sa == 1
5257         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5258         //       => colormod breaks in the case GL_SRC_COLOR only
5259         //   src == GL_DST_ALPHA
5260         //     s*da + d * dst(s, d, sa, da) == d
5261         //       => s == 0
5262         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5263         //       => colormod is never problematic for these
5264
5265         switch(src)
5266         {
5267                 case GL_ZERO:
5268                 case GL_ONE_MINUS_SRC_COLOR:
5269                 case GL_SRC_ALPHA:
5270                 case GL_ONE_MINUS_SRC_ALPHA:
5271                         if(dst == GL_SRC_COLOR)
5272                                 return false;
5273                         return true;
5274                 case GL_ONE:
5275                 case GL_SRC_COLOR:
5276                 case GL_ONE_MINUS_DST_COLOR:
5277                 case GL_DST_ALPHA:
5278                 case GL_ONE_MINUS_DST_ALPHA:
5279                         return true;
5280                 case GL_DST_COLOR:
5281                         if(dst == GL_ONE)
5282                                 return true;
5283                         return false;
5284                 default:
5285                         return false;
5286         }
5287 }
5288 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)
5289 {
5290         // select a permutation of the lighting shader appropriate to this
5291         // combination of texture, entity, light source, and fogging, only use the
5292         // minimum features necessary to avoid wasting rendering time in the
5293         // fragment shader on features that are not being used
5294         unsigned int permutation = 0;
5295         unsigned int mode = 0;
5296         qboolean allow_colormod;
5297         static float dummy_colormod[3] = {1, 1, 1};
5298         float *colormod = rsurface.colormod;
5299         float m16f[16];
5300         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5301         if (rsurfacepass == RSURFPASS_BACKGROUND)
5302         {
5303                 // distorted background
5304                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5305                 {
5306                         mode = SHADERMODE_WATER;
5307                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
5308                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
5309                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5310                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5311                 }
5312                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5313                 {
5314                         mode = SHADERMODE_REFRACTION;
5315                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5316                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5317                 }
5318                 else
5319                 {
5320                         mode = SHADERMODE_GENERIC;
5321                         permutation |= SHADERPERMUTATION_DIFFUSE;
5322                         GL_BlendFunc(GL_ONE, GL_ZERO);
5323                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5324                 }
5325                 GL_AlphaTest(false);
5326         }
5327         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5328         {
5329                 if (r_glsl_offsetmapping.integer)
5330                 {
5331                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5332                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5333                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5334                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5335                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5336                         {
5337                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5338                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5339                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5340                         }
5341                 }
5342                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5343                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5344                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5345                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5346                 // normalmap (deferred prepass), may use alpha test on diffuse
5347                 mode = SHADERMODE_DEFERREDGEOMETRY;
5348                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5349                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5350                 GL_AlphaTest(false);
5351                 GL_BlendFunc(GL_ONE, GL_ZERO);
5352                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5353         }
5354         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5355         {
5356                 if (r_glsl_offsetmapping.integer)
5357                 {
5358                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5359                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5360                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5361                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5362                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5363                         {
5364                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5365                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5366                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5367                         }
5368                 }
5369                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5370                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5371                 // light source
5372                 mode = SHADERMODE_LIGHTSOURCE;
5373                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5374                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5375                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5376                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5377                 if (diffusescale > 0)
5378                         permutation |= SHADERPERMUTATION_DIFFUSE;
5379                 if (specularscale > 0)
5380                 {
5381                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5382                         if (r_shadow_glossexact.integer)
5383                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5384                 }
5385                 if (r_refdef.fogenabled)
5386                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5387                 if (rsurface.texture->colormapping)
5388                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5389                 if (r_shadow_usingshadowmap2d)
5390                 {
5391                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5392                         if(r_shadow_shadowmapvsdct)
5393                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5394
5395                         if (r_shadow_shadowmapsampler)
5396                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5397                         if (r_shadow_shadowmappcf > 1)
5398                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5399                         else if (r_shadow_shadowmappcf)
5400                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5401                 }
5402                 if (rsurface.texture->reflectmasktexture)
5403                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5404                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5405                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5406                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5407         }
5408         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5409         {
5410                 if (r_glsl_offsetmapping.integer)
5411                 {
5412                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5413                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5414                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5415                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5416                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5417                         {
5418                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5419                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5420                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5421                         }
5422                 }
5423                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5424                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5425                 // unshaded geometry (fullbright or ambient model lighting)
5426                 mode = SHADERMODE_FLATCOLOR;
5427                 ambientscale = diffusescale = specularscale = 0;
5428                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5429                         permutation |= SHADERPERMUTATION_GLOW;
5430                 if (r_refdef.fogenabled)
5431                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5432                 if (rsurface.texture->colormapping)
5433                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5434                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5435                 {
5436                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5437                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5438
5439                         if (r_shadow_shadowmapsampler)
5440                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5441                         if (r_shadow_shadowmappcf > 1)
5442                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5443                         else if (r_shadow_shadowmappcf)
5444                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5445                 }
5446                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5447                         permutation |= SHADERPERMUTATION_REFLECTION;
5448                 if (rsurface.texture->reflectmasktexture)
5449                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5450                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5451                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5452                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5453         }
5454         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5455         {
5456                 if (r_glsl_offsetmapping.integer)
5457                 {
5458                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5459                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5460                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5461                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5462                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5463                         {
5464                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5465                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5466                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5467                         }
5468                 }
5469                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5470                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5471                 // directional model lighting
5472                 mode = SHADERMODE_LIGHTDIRECTION;
5473                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5474                         permutation |= SHADERPERMUTATION_GLOW;
5475                 permutation |= SHADERPERMUTATION_DIFFUSE;
5476                 if (specularscale > 0)
5477                 {
5478                         permutation |= SHADERPERMUTATION_SPECULAR;
5479                         if (r_shadow_glossexact.integer)
5480                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5481                 }
5482                 if (r_refdef.fogenabled)
5483                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5484                 if (rsurface.texture->colormapping)
5485                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5486                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5487                 {
5488                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5489                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5490
5491                         if (r_shadow_shadowmapsampler)
5492                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5493                         if (r_shadow_shadowmappcf > 1)
5494                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5495                         else if (r_shadow_shadowmappcf)
5496                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5497                 }
5498                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5499                         permutation |= SHADERPERMUTATION_REFLECTION;
5500                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5501                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5502                 if (rsurface.texture->reflectmasktexture)
5503                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5504                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5505                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5506                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5507         }
5508         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5509         {
5510                 if (r_glsl_offsetmapping.integer)
5511                 {
5512                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5513                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5514                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5515                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5516                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5517                         {
5518                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5519                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5520                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5521                         }
5522                 }
5523                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5524                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5525                 // ambient model lighting
5526                 mode = SHADERMODE_LIGHTDIRECTION;
5527                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5528                         permutation |= SHADERPERMUTATION_GLOW;
5529                 if (r_refdef.fogenabled)
5530                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5531                 if (rsurface.texture->colormapping)
5532                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5533                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5534                 {
5535                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5536                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5537
5538                         if (r_shadow_shadowmapsampler)
5539                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5540                         if (r_shadow_shadowmappcf > 1)
5541                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5542                         else if (r_shadow_shadowmappcf)
5543                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5544                 }
5545                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5546                         permutation |= SHADERPERMUTATION_REFLECTION;
5547                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5548                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5549                 if (rsurface.texture->reflectmasktexture)
5550                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5551                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5552                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5553                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5554         }
5555         else
5556         {
5557                 if (r_glsl_offsetmapping.integer)
5558                 {
5559                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5560                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5561                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5562                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5563                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5564                         {
5565                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5566                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5567                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5568                         }
5569                 }
5570                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5571                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5572                 // lightmapped wall
5573                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5574                         permutation |= SHADERPERMUTATION_GLOW;
5575                 if (r_refdef.fogenabled)
5576                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5577                 if (rsurface.texture->colormapping)
5578                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5579                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5580                 {
5581                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5582                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5583
5584                         if (r_shadow_shadowmapsampler)
5585                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5586                         if (r_shadow_shadowmappcf > 1)
5587                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5588                         else if (r_shadow_shadowmappcf)
5589                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5590                 }
5591                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5592                         permutation |= SHADERPERMUTATION_REFLECTION;
5593                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5594                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5595                 if (rsurface.texture->reflectmasktexture)
5596                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5597                 if (FAKELIGHT_ENABLED)
5598                 {
5599                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5600                         mode = SHADERMODE_FAKELIGHT;
5601                         permutation |= SHADERPERMUTATION_DIFFUSE;
5602                         if (specularscale > 0)
5603                         {
5604                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5605                                 if (r_shadow_glossexact.integer)
5606                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5607                         }
5608                 }
5609                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5610                 {
5611                         // deluxemapping (light direction texture)
5612                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5613                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5614                         else
5615                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5616                         permutation |= SHADERPERMUTATION_DIFFUSE;
5617                         if (specularscale > 0)
5618                         {
5619                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5620                                 if (r_shadow_glossexact.integer)
5621                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5622                         }
5623                 }
5624                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5625                 {
5626                         // fake deluxemapping (uniform light direction in tangentspace)
5627                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5628                         permutation |= SHADERPERMUTATION_DIFFUSE;
5629                         if (specularscale > 0)
5630                         {
5631                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5632                                 if (r_shadow_glossexact.integer)
5633                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5634                         }
5635                 }
5636                 else if (rsurface.uselightmaptexture)
5637                 {
5638                         // ordinary lightmapping (q1bsp, q3bsp)
5639                         mode = SHADERMODE_LIGHTMAP;
5640                 }
5641                 else
5642                 {
5643                         // ordinary vertex coloring (q3bsp)
5644                         mode = SHADERMODE_VERTEXCOLOR;
5645                 }
5646                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5647                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5648                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5649         }
5650         if(!allow_colormod)
5651                 colormod = dummy_colormod;
5652         switch(vid.renderpath)
5653         {
5654         case RENDERPATH_D3D9:
5655 #ifdef SUPPORTD3D
5656                 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);
5657                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5658                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5659                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5660                 if (mode == SHADERMODE_LIGHTSOURCE)
5661                 {
5662                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5663                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5664                 }
5665                 else
5666                 {
5667                         if (mode == SHADERMODE_LIGHTDIRECTION)                                   
5668                         {
5669                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5670                         }
5671                 }
5672                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5673                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5674                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5675                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5676                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5677
5678                 if (mode == SHADERMODE_LIGHTSOURCE)
5679                 {
5680                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5681                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5682                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5683                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5684                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5685
5686                         // additive passes are only darkened by fog, not tinted
5687                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5688                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5689                 }
5690                 else
5691                 {
5692                         if (mode == SHADERMODE_FLATCOLOR)
5693                         {
5694                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5695                         }
5696                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5697                         {
5698                                 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]);
5699                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5700                                 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);
5701                                 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);
5702                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5703                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5704                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5705                         }
5706                         else
5707                         {
5708                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5709                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5710                                 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);
5711                                 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);
5712                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5713                         }
5714                         // additive passes are only darkened by fog, not tinted
5715                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5716                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5717                         else
5718                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5719                         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);
5720                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5721                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5722                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5723                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5724                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5725                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5726                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5727                         if (mode == SHADERMODE_WATER)
5728                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5729                 }
5730                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5731                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5732                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5733                 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));
5734                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5735                 if (rsurface.texture->pantstexture)
5736                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5737                 else
5738                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5739                 if (rsurface.texture->shirttexture)
5740                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5741                 else
5742                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5743                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5744                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5745                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5746                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5747                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5748                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5749                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5750
5751                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5752                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5753                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5754                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5755                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5756                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5757                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5758                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5759                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5760                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5761                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5762                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5763                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5764                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5765                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5766                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5767                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5768                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5769                 {
5770                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5771                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5772                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5773                 }
5774                 else
5775                 {
5776                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5777                 }
5778 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5779 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5780                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5781                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5782                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5783                 {
5784                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5785                         if (rsurface.rtlight)
5786                         {
5787                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5788                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5789                         }
5790                 }
5791 #endif
5792                 break;
5793         case RENDERPATH_D3D10:
5794                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5795                 break;
5796         case RENDERPATH_D3D11:
5797                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5798                 break;
5799         case RENDERPATH_GL20:
5800                 if (gl_mesh_separatearrays.integer)
5801                 {
5802                         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);
5803                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5804                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5805                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5806                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5807                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5808                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5809                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5810                 }
5811                 else
5812                 {
5813                         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);
5814                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5815                 }
5816                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5817                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5818                 if (mode == SHADERMODE_LIGHTSOURCE)
5819                 {
5820                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5821                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5822                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5823                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5824                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5825                         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);
5826         
5827                         // additive passes are only darkened by fog, not tinted
5828                         if (r_glsl_permutation->loc_FogColor >= 0)
5829                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5830                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5831                 }
5832                 else
5833                 {
5834                         if (mode == SHADERMODE_FLATCOLOR)
5835                         {
5836                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5837                         }
5838                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5839                         {
5840                                 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]);
5841                                 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]);
5842                                 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);
5843                                 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);
5844                                 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);
5845                                 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]);
5846                                 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]);
5847                         }
5848                         else
5849                         {
5850                                 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]);
5851                                 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]);
5852                                 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);
5853                                 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);
5854                                 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);
5855                         }
5856                         // additive passes are only darkened by fog, not tinted
5857                         if (r_glsl_permutation->loc_FogColor >= 0)
5858                         {
5859                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5860                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5861                                 else
5862                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5863                         }
5864                         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);
5865                         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]);
5866                         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]);
5867                         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]);
5868                         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]);
5869                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5870                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5871                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5872                         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]);
5873                 }
5874                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5875                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5876                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5877                 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]);
5878                 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]);
5879
5880                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5881                 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));
5882                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5883                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5884                 {
5885                         if (rsurface.texture->pantstexture)
5886                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5887                         else
5888                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5889                 }
5890                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5891                 {
5892                         if (rsurface.texture->shirttexture)
5893                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5894                         else
5895                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5896                 }
5897                 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]);
5898                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5899                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5900                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5901                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5902                 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]);
5903                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5904
5905         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5906         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5907         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5908                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5909                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5910                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5911                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5912                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5913                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5914                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5915                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5916                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5917                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5918                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5919                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5920                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5921                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5922                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5923                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5924                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5925                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5926                 {
5927                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5928                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5929                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5930                 }
5931                 else
5932                 {
5933                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5934                 }
5935 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5936 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5937                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5938                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5939                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5940                 {
5941                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5942                         if (rsurface.rtlight)
5943                         {
5944                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5945                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5946                         }
5947                 }
5948                 CHECKGLERROR
5949                 break;
5950         case RENDERPATH_CGGL:
5951 #ifdef SUPPORTCG
5952                 if (gl_mesh_separatearrays.integer)
5953                 {
5954                         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);
5955                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5956                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5957                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5958                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5959                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5960                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5961                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5962                 }
5963                 else
5964                 {
5965                         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);
5966                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5967                 }
5968                 R_SetupShader_SetPermutationCG(mode, permutation);
5969                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5970                 if (mode == SHADERMODE_LIGHTSOURCE)
5971                 {
5972                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5973                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5974                 }
5975                 else
5976                 {
5977                         if (mode == SHADERMODE_LIGHTDIRECTION)
5978                         {
5979                                 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
5980                         }
5981                 }
5982                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5983                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5984                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5985                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5986                 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
5987                 CHECKGLERROR
5988
5989                 if (mode == SHADERMODE_LIGHTSOURCE)
5990                 {
5991                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5992                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5993                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
5994                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
5995                         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
5996
5997                         // additive passes are only darkened by fog, not tinted
5998                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5999                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6000                 }
6001                 else
6002                 {
6003                         if (mode == SHADERMODE_FLATCOLOR)
6004                         {
6005                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6006                         }
6007                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6008                         {
6009                                 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
6010                                 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
6011                                 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
6012                                 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
6013                                 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
6014                                 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
6015                                 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
6016                         }
6017                         else
6018                         {
6019                                 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
6020                                 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
6021                                 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
6022                                 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
6023                                 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
6024                         }
6025                         // additive passes are only darkened by fog, not tinted
6026                         if (r_cg_permutation->fp_FogColor)
6027                         {
6028                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6029                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6030                                 else
6031                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6032                                 CHECKCGERROR
6033                         }
6034                         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
6035                         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
6036                         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
6037                         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
6038                         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
6039                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6040                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6041                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6042                         if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6043                 }
6044                 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
6045                 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
6046                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6047                 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
6048                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6049                 if (r_cg_permutation->fp_Color_Pants)
6050                 {
6051                         if (rsurface.texture->pantstexture)
6052                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6053                         else
6054                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6055                         CHECKCGERROR
6056                 }
6057                 if (r_cg_permutation->fp_Color_Shirt)
6058                 {
6059                         if (rsurface.texture->shirttexture)
6060                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6061                         else
6062                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6063                         CHECKCGERROR
6064                 }
6065                 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
6066                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6067                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6068                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6069                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6070                 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
6071                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6072
6073         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
6074         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
6075         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
6076                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
6077                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
6078                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
6079                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
6080                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
6081                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
6082                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
6083                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
6084                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
6085                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
6086                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
6087                 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
6088                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
6089                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
6090                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6091                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6092                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6093                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6094                 {
6095                         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
6096                         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
6097                         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
6098                 }
6099                 else
6100                 {
6101                         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
6102                 }
6103                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6104                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6105                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
6106                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
6107                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6108                 {
6109                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6110                         if (rsurface.rtlight)
6111                         {
6112                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6113                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6114                         }
6115                 }
6116
6117                 CHECKGLERROR
6118 #endif
6119                 break;
6120         case RENDERPATH_GL13:
6121         case RENDERPATH_GL11:
6122                 break;
6123         }
6124 }
6125
6126 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6127 {
6128         // select a permutation of the lighting shader appropriate to this
6129         // combination of texture, entity, light source, and fogging, only use the
6130         // minimum features necessary to avoid wasting rendering time in the
6131         // fragment shader on features that are not being used
6132         unsigned int permutation = 0;
6133         unsigned int mode = 0;
6134         const float *lightcolorbase = rtlight->currentcolor;
6135         float ambientscale = rtlight->ambientscale;
6136         float diffusescale = rtlight->diffusescale;
6137         float specularscale = rtlight->specularscale;
6138         // this is the location of the light in view space
6139         vec3_t viewlightorigin;
6140         // this transforms from view space (camera) to light space (cubemap)
6141         matrix4x4_t viewtolight;
6142         matrix4x4_t lighttoview;
6143         float viewtolight16f[16];
6144         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6145         // light source
6146         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6147         if (rtlight->currentcubemap != r_texture_whitecube)
6148                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6149         if (diffusescale > 0)
6150                 permutation |= SHADERPERMUTATION_DIFFUSE;
6151         if (specularscale > 0)
6152         {
6153                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6154                 if (r_shadow_glossexact.integer)
6155                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
6156         }
6157         if (r_shadow_usingshadowmap2d)
6158         {
6159                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6160                 if (r_shadow_shadowmapvsdct)
6161                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6162
6163                 if (r_shadow_shadowmapsampler)
6164                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6165                 if (r_shadow_shadowmappcf > 1)
6166                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6167                 else if (r_shadow_shadowmappcf)
6168                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6169         }
6170         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6171         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6172         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6173         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6174         switch(vid.renderpath)
6175         {
6176         case RENDERPATH_D3D9:
6177 #ifdef SUPPORTD3D
6178                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6179                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6180                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6181                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6182                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6183                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6184                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6185                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6186                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6187                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6188                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6189
6190                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6191                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
6192                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6193                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6194                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
6195                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6196 #endif
6197                 break;
6198         case RENDERPATH_D3D10:
6199                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6200                 break;
6201         case RENDERPATH_D3D11:
6202                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6203                 break;
6204         case RENDERPATH_GL20:
6205                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6206                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6207                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6208                 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);
6209                 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);
6210                 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);
6211                 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]);
6212                 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]);
6213                 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));
6214                 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]);
6215                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6216
6217                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6218                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6219                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6220                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6221                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6222                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6223                 break;
6224         case RENDERPATH_CGGL:
6225 #ifdef SUPPORTCG
6226                 R_SetupShader_SetPermutationCG(mode, permutation);
6227                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6228                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6229                 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
6230                 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
6231                 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
6232                 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
6233                 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
6234                 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
6235                 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
6236                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6237
6238                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6239                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6240                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6241                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6242                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6243                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6244 #endif
6245                 break;
6246         case RENDERPATH_GL13:
6247         case RENDERPATH_GL11:
6248                 break;
6249         }
6250 }
6251
6252 #define SKINFRAME_HASH 1024
6253
6254 typedef struct
6255 {
6256         int loadsequence; // incremented each level change
6257         memexpandablearray_t array;
6258         skinframe_t *hash[SKINFRAME_HASH];
6259 }
6260 r_skinframe_t;
6261 r_skinframe_t r_skinframe;
6262
6263 void R_SkinFrame_PrepareForPurge(void)
6264 {
6265         r_skinframe.loadsequence++;
6266         // wrap it without hitting zero
6267         if (r_skinframe.loadsequence >= 200)
6268                 r_skinframe.loadsequence = 1;
6269 }
6270
6271 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6272 {
6273         if (!skinframe)
6274                 return;
6275         // mark the skinframe as used for the purging code
6276         skinframe->loadsequence = r_skinframe.loadsequence;
6277 }
6278
6279 void R_SkinFrame_Purge(void)
6280 {
6281         int i;
6282         skinframe_t *s;
6283         for (i = 0;i < SKINFRAME_HASH;i++)
6284         {
6285                 for (s = r_skinframe.hash[i];s;s = s->next)
6286                 {
6287                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6288                         {
6289                                 if (s->merged == s->base)
6290                                         s->merged = NULL;
6291                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6292                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6293                                 R_PurgeTexture(s->merged);s->merged = NULL;
6294                                 R_PurgeTexture(s->base  );s->base   = NULL;
6295                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6296                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6297                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6298                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6299                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6300                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6301                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6302                                 s->loadsequence = 0;
6303                         }
6304                 }
6305         }
6306 }
6307
6308 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6309         skinframe_t *item;
6310         char basename[MAX_QPATH];
6311
6312         Image_StripImageExtension(name, basename, sizeof(basename));
6313
6314         if( last == NULL ) {
6315                 int hashindex;
6316                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6317                 item = r_skinframe.hash[hashindex];
6318         } else {
6319                 item = last->next;
6320         }
6321
6322         // linearly search through the hash bucket
6323         for( ; item ; item = item->next ) {
6324                 if( !strcmp( item->basename, basename ) ) {
6325                         return item;
6326                 }
6327         }
6328         return NULL;
6329 }
6330
6331 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6332 {
6333         skinframe_t *item;
6334         int hashindex;
6335         char basename[MAX_QPATH];
6336
6337         Image_StripImageExtension(name, basename, sizeof(basename));
6338
6339         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6340         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6341                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6342                         break;
6343
6344         if (!item) {
6345                 rtexture_t *dyntexture;
6346                 // check whether its a dynamic texture
6347                 dyntexture = CL_GetDynTexture( basename );
6348                 if (!add && !dyntexture)
6349                         return NULL;
6350                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6351                 memset(item, 0, sizeof(*item));
6352                 strlcpy(item->basename, basename, sizeof(item->basename));
6353                 item->base = dyntexture; // either NULL or dyntexture handle
6354                 item->textureflags = textureflags;
6355                 item->comparewidth = comparewidth;
6356                 item->compareheight = compareheight;
6357                 item->comparecrc = comparecrc;
6358                 item->next = r_skinframe.hash[hashindex];
6359                 r_skinframe.hash[hashindex] = item;
6360         }
6361         else if( item->base == NULL )
6362         {
6363                 rtexture_t *dyntexture;
6364                 // check whether its a dynamic texture
6365                 // 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]
6366                 dyntexture = CL_GetDynTexture( basename );
6367                 item->base = dyntexture; // either NULL or dyntexture handle
6368         }
6369
6370         R_SkinFrame_MarkUsed(item);
6371         return item;
6372 }
6373
6374 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6375         { \
6376                 unsigned long long avgcolor[5], wsum; \
6377                 int pix, comp, w; \
6378                 avgcolor[0] = 0; \
6379                 avgcolor[1] = 0; \
6380                 avgcolor[2] = 0; \
6381                 avgcolor[3] = 0; \
6382                 avgcolor[4] = 0; \
6383                 wsum = 0; \
6384                 for(pix = 0; pix < cnt; ++pix) \
6385                 { \
6386                         w = 0; \
6387                         for(comp = 0; comp < 3; ++comp) \
6388                                 w += getpixel; \
6389                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6390                         { \
6391                                 ++wsum; \
6392                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6393                                 w = getpixel; \
6394                                 for(comp = 0; comp < 3; ++comp) \
6395                                         avgcolor[comp] += getpixel * w; \
6396                                 avgcolor[3] += w; \
6397                         } \
6398                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6399                         avgcolor[4] += getpixel; \
6400                 } \
6401                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6402                         avgcolor[3] = 1; \
6403                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6404                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6405                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6406                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6407         }
6408
6409 extern cvar_t gl_picmip;
6410 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6411 {
6412         int j;
6413         unsigned char *pixels;
6414         unsigned char *bumppixels;
6415         unsigned char *basepixels = NULL;
6416         int basepixels_width = 0;
6417         int basepixels_height = 0;
6418         skinframe_t *skinframe;
6419         rtexture_t *ddsbase = NULL;
6420         qboolean ddshasalpha = false;
6421         float ddsavgcolor[4];
6422         char basename[MAX_QPATH];
6423         int miplevel = R_PicmipForFlags(textureflags);
6424         int savemiplevel = miplevel;
6425         int mymiplevel;
6426
6427         if (cls.state == ca_dedicated)
6428                 return NULL;
6429
6430         // return an existing skinframe if already loaded
6431         // if loading of the first image fails, don't make a new skinframe as it
6432         // would cause all future lookups of this to be missing
6433         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6434         if (skinframe && skinframe->base)
6435                 return skinframe;
6436
6437         Image_StripImageExtension(name, basename, sizeof(basename));
6438
6439         // check for DDS texture file first
6440         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6441         {
6442                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6443                 if (basepixels == NULL)
6444                         return NULL;
6445         }
6446
6447         // FIXME handle miplevel
6448
6449         if (developer_loading.integer)
6450                 Con_Printf("loading skin \"%s\"\n", name);
6451
6452         // we've got some pixels to store, so really allocate this new texture now
6453         if (!skinframe)
6454                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6455         skinframe->stain = NULL;
6456         skinframe->merged = NULL;
6457         skinframe->base = NULL;
6458         skinframe->pants = NULL;
6459         skinframe->shirt = NULL;
6460         skinframe->nmap = NULL;
6461         skinframe->gloss = NULL;
6462         skinframe->glow = NULL;
6463         skinframe->fog = NULL;
6464         skinframe->reflect = NULL;
6465         skinframe->hasalpha = false;
6466
6467         if (ddsbase)
6468         {
6469                 skinframe->base = ddsbase;
6470                 skinframe->hasalpha = ddshasalpha;
6471                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6472                 if (r_loadfog && skinframe->hasalpha)
6473                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6474                 //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]);
6475         }
6476         else
6477         {
6478                 basepixels_width = image_width;
6479                 basepixels_height = image_height;
6480                 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);
6481                 if (textureflags & TEXF_ALPHA)
6482                 {
6483                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6484                         {
6485                                 if (basepixels[j] < 255)
6486                                 {
6487                                         skinframe->hasalpha = true;
6488                                         break;
6489                                 }
6490                         }
6491                         if (r_loadfog && skinframe->hasalpha)
6492                         {
6493                                 // has transparent pixels
6494                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6495                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6496                                 {
6497                                         pixels[j+0] = 255;
6498                                         pixels[j+1] = 255;
6499                                         pixels[j+2] = 255;
6500                                         pixels[j+3] = basepixels[j+3];
6501                                 }
6502                                 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);
6503                                 Mem_Free(pixels);
6504                         }
6505                 }
6506                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6507                 //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]);
6508                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6509                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6510                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6511                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6512         }
6513
6514         if (r_loaddds)
6515         {
6516                 mymiplevel = savemiplevel;
6517                 if (r_loadnormalmap)
6518                         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);
6519                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6520                 if (r_loadgloss)
6521                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6522                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6523                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6524                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6525         }
6526
6527         // _norm is the name used by tenebrae and has been adopted as standard
6528         if (r_loadnormalmap && skinframe->nmap == NULL)
6529         {
6530                 mymiplevel = savemiplevel;
6531                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6532                 {
6533                         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);
6534                         Mem_Free(pixels);
6535                         pixels = NULL;
6536                 }
6537                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6538                 {
6539                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6540                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6541                         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);
6542                         Mem_Free(pixels);
6543                         Mem_Free(bumppixels);
6544                 }
6545                 else if (r_shadow_bumpscale_basetexture.value > 0)
6546                 {
6547                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6548                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6549                         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);
6550                         Mem_Free(pixels);
6551                 }
6552                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6553                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6554         }
6555
6556         // _luma is supported only for tenebrae compatibility
6557         // _glow is the preferred name
6558         mymiplevel = savemiplevel;
6559         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))))
6560         {
6561                 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);
6562                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6563                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6564                 Mem_Free(pixels);pixels = NULL;
6565         }
6566
6567         mymiplevel = savemiplevel;
6568         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6569         {
6570                 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);
6571                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6572                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6573                 Mem_Free(pixels);
6574                 pixels = NULL;
6575         }
6576
6577         mymiplevel = savemiplevel;
6578         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6579         {
6580                 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);
6581                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6582                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6583                 Mem_Free(pixels);
6584                 pixels = NULL;
6585         }
6586
6587         mymiplevel = savemiplevel;
6588         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6589         {
6590                 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);
6591                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6592                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6593                 Mem_Free(pixels);
6594                 pixels = NULL;
6595         }
6596
6597         mymiplevel = savemiplevel;
6598         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6599         {
6600                 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);
6601                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6602                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6603                 Mem_Free(pixels);
6604                 pixels = NULL;
6605         }
6606
6607         if (basepixels)
6608                 Mem_Free(basepixels);
6609
6610         return skinframe;
6611 }
6612
6613 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6614 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6615 {
6616         int i;
6617         unsigned char *temp1, *temp2;
6618         skinframe_t *skinframe;
6619
6620         if (cls.state == ca_dedicated)
6621                 return NULL;
6622
6623         // if already loaded just return it, otherwise make a new skinframe
6624         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6625         if (skinframe && skinframe->base)
6626                 return skinframe;
6627
6628         skinframe->stain = NULL;
6629         skinframe->merged = NULL;
6630         skinframe->base = NULL;
6631         skinframe->pants = NULL;
6632         skinframe->shirt = NULL;
6633         skinframe->nmap = NULL;
6634         skinframe->gloss = NULL;
6635         skinframe->glow = NULL;
6636         skinframe->fog = NULL;
6637         skinframe->reflect = NULL;
6638         skinframe->hasalpha = false;
6639
6640         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6641         if (!skindata)
6642                 return NULL;
6643
6644         if (developer_loading.integer)
6645                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6646
6647         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6648         {
6649                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6650                 temp2 = temp1 + width * height * 4;
6651                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6652                 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);
6653                 Mem_Free(temp1);
6654         }
6655         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6656         if (textureflags & TEXF_ALPHA)
6657         {
6658                 for (i = 3;i < width * height * 4;i += 4)
6659                 {
6660                         if (skindata[i] < 255)
6661                         {
6662                                 skinframe->hasalpha = true;
6663                                 break;
6664                         }
6665                 }
6666                 if (r_loadfog && skinframe->hasalpha)
6667                 {
6668                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6669                         memcpy(fogpixels, skindata, width * height * 4);
6670                         for (i = 0;i < width * height * 4;i += 4)
6671                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6672                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6673                         Mem_Free(fogpixels);
6674                 }
6675         }
6676
6677         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6678         //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]);
6679
6680         return skinframe;
6681 }
6682
6683 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6684 {
6685         int i;
6686         int featuresmask;
6687         skinframe_t *skinframe;
6688
6689         if (cls.state == ca_dedicated)
6690                 return NULL;
6691
6692         // if already loaded just return it, otherwise make a new skinframe
6693         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6694         if (skinframe && skinframe->base)
6695                 return skinframe;
6696
6697         skinframe->stain = NULL;
6698         skinframe->merged = NULL;
6699         skinframe->base = NULL;
6700         skinframe->pants = NULL;
6701         skinframe->shirt = NULL;
6702         skinframe->nmap = NULL;
6703         skinframe->gloss = NULL;
6704         skinframe->glow = NULL;
6705         skinframe->fog = NULL;
6706         skinframe->reflect = NULL;
6707         skinframe->hasalpha = false;
6708
6709         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6710         if (!skindata)
6711                 return NULL;
6712
6713         if (developer_loading.integer)
6714                 Con_Printf("loading quake skin \"%s\"\n", name);
6715
6716         // 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)
6717         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6718         memcpy(skinframe->qpixels, skindata, width*height);
6719         skinframe->qwidth = width;
6720         skinframe->qheight = height;
6721
6722         featuresmask = 0;
6723         for (i = 0;i < width * height;i++)
6724                 featuresmask |= palette_featureflags[skindata[i]];
6725
6726         skinframe->hasalpha = false;
6727         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6728         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6729         skinframe->qgeneratemerged = true;
6730         skinframe->qgeneratebase = skinframe->qhascolormapping;
6731         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6732
6733         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6734         //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]);
6735
6736         return skinframe;
6737 }
6738
6739 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6740 {
6741         int width;
6742         int height;
6743         unsigned char *skindata;
6744
6745         if (!skinframe->qpixels)
6746                 return;
6747
6748         if (!skinframe->qhascolormapping)
6749                 colormapped = false;
6750
6751         if (colormapped)
6752         {
6753                 if (!skinframe->qgeneratebase)
6754                         return;
6755         }
6756         else
6757         {
6758                 if (!skinframe->qgeneratemerged)
6759                         return;
6760         }
6761
6762         width = skinframe->qwidth;
6763         height = skinframe->qheight;
6764         skindata = skinframe->qpixels;
6765
6766         if (skinframe->qgeneratenmap)
6767         {
6768                 unsigned char *temp1, *temp2;
6769                 skinframe->qgeneratenmap = false;
6770                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6771                 temp2 = temp1 + width * height * 4;
6772                 // use either a custom palette or the quake palette
6773                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6774                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6775                 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);
6776                 Mem_Free(temp1);
6777         }
6778
6779         if (skinframe->qgenerateglow)
6780         {
6781                 skinframe->qgenerateglow = false;
6782                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6783         }
6784
6785         if (colormapped)
6786         {
6787                 skinframe->qgeneratebase = false;
6788                 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);
6789                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6790                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6791         }
6792         else
6793         {
6794                 skinframe->qgeneratemerged = false;
6795                 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);
6796         }
6797
6798         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6799         {
6800                 Mem_Free(skinframe->qpixels);
6801                 skinframe->qpixels = NULL;
6802         }
6803 }
6804
6805 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)
6806 {
6807         int i;
6808         skinframe_t *skinframe;
6809
6810         if (cls.state == ca_dedicated)
6811                 return NULL;
6812
6813         // if already loaded just return it, otherwise make a new skinframe
6814         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6815         if (skinframe && skinframe->base)
6816                 return skinframe;
6817
6818         skinframe->stain = NULL;
6819         skinframe->merged = NULL;
6820         skinframe->base = NULL;
6821         skinframe->pants = NULL;
6822         skinframe->shirt = NULL;
6823         skinframe->nmap = NULL;
6824         skinframe->gloss = NULL;
6825         skinframe->glow = NULL;
6826         skinframe->fog = NULL;
6827         skinframe->reflect = NULL;
6828         skinframe->hasalpha = false;
6829
6830         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6831         if (!skindata)
6832                 return NULL;
6833
6834         if (developer_loading.integer)
6835                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6836
6837         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6838         if (textureflags & TEXF_ALPHA)
6839         {
6840                 for (i = 0;i < width * height;i++)
6841                 {
6842                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6843                         {
6844                                 skinframe->hasalpha = true;
6845                                 break;
6846                         }
6847                 }
6848                 if (r_loadfog && skinframe->hasalpha)
6849                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6850         }
6851
6852         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6853         //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]);
6854
6855         return skinframe;
6856 }
6857
6858 skinframe_t *R_SkinFrame_LoadMissing(void)
6859 {
6860         skinframe_t *skinframe;
6861
6862         if (cls.state == ca_dedicated)
6863                 return NULL;
6864
6865         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6866         skinframe->stain = NULL;
6867         skinframe->merged = NULL;
6868         skinframe->base = NULL;
6869         skinframe->pants = NULL;
6870         skinframe->shirt = NULL;
6871         skinframe->nmap = NULL;
6872         skinframe->gloss = NULL;
6873         skinframe->glow = NULL;
6874         skinframe->fog = NULL;
6875         skinframe->reflect = NULL;
6876         skinframe->hasalpha = false;
6877
6878         skinframe->avgcolor[0] = rand() / RAND_MAX;
6879         skinframe->avgcolor[1] = rand() / RAND_MAX;
6880         skinframe->avgcolor[2] = rand() / RAND_MAX;
6881         skinframe->avgcolor[3] = 1;
6882
6883         return skinframe;
6884 }
6885
6886 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6887 typedef struct suffixinfo_s
6888 {
6889         const char *suffix;
6890         qboolean flipx, flipy, flipdiagonal;
6891 }
6892 suffixinfo_t;
6893 static suffixinfo_t suffix[3][6] =
6894 {
6895         {
6896                 {"px",   false, false, false},
6897                 {"nx",   false, false, false},
6898                 {"py",   false, false, false},
6899                 {"ny",   false, false, false},
6900                 {"pz",   false, false, false},
6901                 {"nz",   false, false, false}
6902         },
6903         {
6904                 {"posx", false, false, false},
6905                 {"negx", false, false, false},
6906                 {"posy", false, false, false},
6907                 {"negy", false, false, false},
6908                 {"posz", false, false, false},
6909                 {"negz", false, false, false}
6910         },
6911         {
6912                 {"rt",    true, false,  true},
6913                 {"lf",   false,  true,  true},
6914                 {"ft",    true,  true, false},
6915                 {"bk",   false, false, false},
6916                 {"up",    true, false,  true},
6917                 {"dn",    true, false,  true}
6918         }
6919 };
6920
6921 static int componentorder[4] = {0, 1, 2, 3};
6922
6923 rtexture_t *R_LoadCubemap(const char *basename)
6924 {
6925         int i, j, cubemapsize;
6926         unsigned char *cubemappixels, *image_buffer;
6927         rtexture_t *cubemaptexture;
6928         char name[256];
6929         // must start 0 so the first loadimagepixels has no requested width/height
6930         cubemapsize = 0;
6931         cubemappixels = NULL;
6932         cubemaptexture = NULL;
6933         // keep trying different suffix groups (posx, px, rt) until one loads
6934         for (j = 0;j < 3 && !cubemappixels;j++)
6935         {
6936                 // load the 6 images in the suffix group
6937                 for (i = 0;i < 6;i++)
6938                 {
6939                         // generate an image name based on the base and and suffix
6940                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6941                         // load it
6942                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6943                         {
6944                                 // an image loaded, make sure width and height are equal
6945                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6946                                 {
6947                                         // if this is the first image to load successfully, allocate the cubemap memory
6948                                         if (!cubemappixels && image_width >= 1)
6949                                         {
6950                                                 cubemapsize = image_width;
6951                                                 // note this clears to black, so unavailable sides are black
6952                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6953                                         }
6954                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6955                                         if (cubemappixels)
6956                                                 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);
6957                                 }
6958                                 else
6959                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6960                                 // free the image
6961                                 Mem_Free(image_buffer);
6962                         }
6963                 }
6964         }
6965         // if a cubemap loaded, upload it
6966         if (cubemappixels)
6967         {
6968                 if (developer_loading.integer)
6969                         Con_Printf("loading cubemap \"%s\"\n", basename);
6970
6971                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6972                 Mem_Free(cubemappixels);
6973         }
6974         else
6975         {
6976                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6977                 if (developer_loading.integer)
6978                 {
6979                         Con_Printf("(tried tried images ");
6980                         for (j = 0;j < 3;j++)
6981                                 for (i = 0;i < 6;i++)
6982                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6983                         Con_Print(" and was unable to find any of them).\n");
6984                 }
6985         }
6986         return cubemaptexture;
6987 }
6988
6989 rtexture_t *R_GetCubemap(const char *basename)
6990 {
6991         int i;
6992         for (i = 0;i < r_texture_numcubemaps;i++)
6993                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6994                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6995         if (i >= MAX_CUBEMAPS)
6996                 return r_texture_whitecube;
6997         r_texture_numcubemaps++;
6998         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6999         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7000         return r_texture_cubemaps[i].texture;
7001 }
7002
7003 void R_FreeCubemaps(void)
7004 {
7005         int i;
7006         for (i = 0;i < r_texture_numcubemaps;i++)
7007         {
7008                 if (developer_loading.integer)
7009                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7010                 if (r_texture_cubemaps[i].texture)
7011                         R_FreeTexture(r_texture_cubemaps[i].texture);
7012         }
7013         r_texture_numcubemaps = 0;
7014 }
7015
7016 void R_Main_FreeViewCache(void)
7017 {
7018         if (r_refdef.viewcache.entityvisible)
7019                 Mem_Free(r_refdef.viewcache.entityvisible);
7020         if (r_refdef.viewcache.world_pvsbits)
7021                 Mem_Free(r_refdef.viewcache.world_pvsbits);
7022         if (r_refdef.viewcache.world_leafvisible)
7023                 Mem_Free(r_refdef.viewcache.world_leafvisible);
7024         if (r_refdef.viewcache.world_surfacevisible)
7025                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7026         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7027 }
7028
7029 void R_Main_ResizeViewCache(void)
7030 {
7031         int numentities = r_refdef.scene.numentities;
7032         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7033         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7034         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7035         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7036         if (r_refdef.viewcache.maxentities < numentities)
7037         {
7038                 r_refdef.viewcache.maxentities = numentities;
7039                 if (r_refdef.viewcache.entityvisible)
7040                         Mem_Free(r_refdef.viewcache.entityvisible);
7041                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7042         }
7043         if (r_refdef.viewcache.world_numclusters != numclusters)
7044         {
7045                 r_refdef.viewcache.world_numclusters = numclusters;
7046                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7047                 if (r_refdef.viewcache.world_pvsbits)
7048                         Mem_Free(r_refdef.viewcache.world_pvsbits);
7049                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7050         }
7051         if (r_refdef.viewcache.world_numleafs != numleafs)
7052         {
7053                 r_refdef.viewcache.world_numleafs = numleafs;
7054                 if (r_refdef.viewcache.world_leafvisible)
7055                         Mem_Free(r_refdef.viewcache.world_leafvisible);
7056                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7057         }
7058         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7059         {
7060                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7061                 if (r_refdef.viewcache.world_surfacevisible)
7062                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
7063                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7064         }
7065 }
7066
7067 extern rtexture_t *loadingscreentexture;
7068 void gl_main_start(void)
7069 {
7070         loadingscreentexture = NULL;
7071         r_texture_blanknormalmap = NULL;
7072         r_texture_white = NULL;
7073         r_texture_grey128 = NULL;
7074         r_texture_black = NULL;
7075         r_texture_whitecube = NULL;
7076         r_texture_normalizationcube = NULL;
7077         r_texture_fogattenuation = NULL;
7078         r_texture_fogheighttexture = NULL;
7079         r_texture_gammaramps = NULL;
7080         r_texture_numcubemaps = 0;
7081
7082         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
7083         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7084
7085         switch(vid.renderpath)
7086         {
7087         case RENDERPATH_GL20:
7088         case RENDERPATH_CGGL:
7089         case RENDERPATH_D3D9:
7090         case RENDERPATH_D3D10:
7091         case RENDERPATH_D3D11:
7092                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7093                 Cvar_SetValueQuick(&gl_combine, 1);
7094                 Cvar_SetValueQuick(&r_glsl, 1);
7095                 r_loadnormalmap = true;
7096                 r_loadgloss = true;
7097                 r_loadfog = false;
7098                 break;
7099         case RENDERPATH_GL13:
7100                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7101                 Cvar_SetValueQuick(&gl_combine, 1);
7102                 Cvar_SetValueQuick(&r_glsl, 0);
7103                 r_loadnormalmap = false;
7104                 r_loadgloss = false;
7105                 r_loadfog = true;
7106                 break;
7107         case RENDERPATH_GL11:
7108                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7109                 Cvar_SetValueQuick(&gl_combine, 0);
7110                 Cvar_SetValueQuick(&r_glsl, 0);
7111                 r_loadnormalmap = false;
7112                 r_loadgloss = false;
7113                 r_loadfog = true;
7114                 break;
7115         }
7116
7117         R_AnimCache_Free();
7118         R_FrameData_Reset();
7119
7120         r_numqueries = 0;
7121         r_maxqueries = 0;
7122         memset(r_queries, 0, sizeof(r_queries));
7123
7124         r_qwskincache = NULL;
7125         r_qwskincache_size = 0;
7126
7127         // set up r_skinframe loading system for textures
7128         memset(&r_skinframe, 0, sizeof(r_skinframe));
7129         r_skinframe.loadsequence = 1;
7130         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7131
7132         r_main_texturepool = R_AllocTexturePool();
7133         R_BuildBlankTextures();
7134         R_BuildNoTexture();
7135         if (vid.support.arb_texture_cube_map)
7136         {
7137                 R_BuildWhiteCube();
7138                 R_BuildNormalizationCube();
7139         }
7140         r_texture_fogattenuation = NULL;
7141         r_texture_fogheighttexture = NULL;
7142         r_texture_gammaramps = NULL;
7143         //r_texture_fogintensity = NULL;
7144         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7145         memset(&r_waterstate, 0, sizeof(r_waterstate));
7146         r_glsl_permutation = NULL;
7147         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7148         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7149         glslshaderstring = NULL;
7150 #ifdef SUPPORTCG
7151         r_cg_permutation = NULL;
7152         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7153         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7154         cgshaderstring = NULL;
7155 #endif
7156 #ifdef SUPPORTD3D
7157         r_hlsl_permutation = NULL;
7158         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7159         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7160         hlslshaderstring = NULL;
7161 #endif
7162         memset(&r_svbsp, 0, sizeof (r_svbsp));
7163
7164         r_refdef.fogmasktable_density = 0;
7165 }
7166
7167 void gl_main_shutdown(void)
7168 {
7169         R_AnimCache_Free();
7170         R_FrameData_Reset();
7171
7172         R_Main_FreeViewCache();
7173
7174         switch(vid.renderpath)
7175         {
7176         case RENDERPATH_GL11:
7177         case RENDERPATH_GL13:
7178         case RENDERPATH_GL20:
7179         case RENDERPATH_CGGL:
7180                 if (r_maxqueries)
7181                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7182                 break;
7183         case RENDERPATH_D3D9:
7184                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7185                 break;
7186         case RENDERPATH_D3D10:
7187                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7188                 break;
7189         case RENDERPATH_D3D11:
7190                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7191                 break;
7192         }
7193
7194         r_numqueries = 0;
7195         r_maxqueries = 0;
7196         memset(r_queries, 0, sizeof(r_queries));
7197
7198         r_qwskincache = NULL;
7199         r_qwskincache_size = 0;
7200
7201         // clear out the r_skinframe state
7202         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7203         memset(&r_skinframe, 0, sizeof(r_skinframe));
7204
7205         if (r_svbsp.nodes)
7206                 Mem_Free(r_svbsp.nodes);
7207         memset(&r_svbsp, 0, sizeof (r_svbsp));
7208         R_FreeTexturePool(&r_main_texturepool);
7209         loadingscreentexture = NULL;
7210         r_texture_blanknormalmap = NULL;
7211         r_texture_white = NULL;
7212         r_texture_grey128 = NULL;
7213         r_texture_black = NULL;
7214         r_texture_whitecube = NULL;
7215         r_texture_normalizationcube = NULL;
7216         r_texture_fogattenuation = NULL;
7217         r_texture_fogheighttexture = NULL;
7218         r_texture_gammaramps = NULL;
7219         r_texture_numcubemaps = 0;
7220         //r_texture_fogintensity = NULL;
7221         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7222         memset(&r_waterstate, 0, sizeof(r_waterstate));
7223         R_GLSL_Restart_f();
7224 }
7225
7226 extern void CL_ParseEntityLump(char *entitystring);
7227 void gl_main_newmap(void)
7228 {
7229         // FIXME: move this code to client
7230         char *entities, entname[MAX_QPATH];
7231         if (r_qwskincache)
7232                 Mem_Free(r_qwskincache);
7233         r_qwskincache = NULL;
7234         r_qwskincache_size = 0;
7235         if (cl.worldmodel)
7236         {
7237                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7238                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7239                 {
7240                         CL_ParseEntityLump(entities);
7241                         Mem_Free(entities);
7242                         return;
7243                 }
7244                 if (cl.worldmodel->brush.entities)
7245                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7246         }
7247         R_Main_FreeViewCache();
7248
7249         R_FrameData_Reset();
7250 }
7251
7252 void GL_Main_Init(void)
7253 {
7254         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7255
7256         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7257         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7258         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7259         if (gamemode == GAME_NEHAHRA)
7260         {
7261                 Cvar_RegisterVariable (&gl_fogenable);
7262                 Cvar_RegisterVariable (&gl_fogdensity);
7263                 Cvar_RegisterVariable (&gl_fogred);
7264                 Cvar_RegisterVariable (&gl_foggreen);
7265                 Cvar_RegisterVariable (&gl_fogblue);
7266                 Cvar_RegisterVariable (&gl_fogstart);
7267                 Cvar_RegisterVariable (&gl_fogend);
7268                 Cvar_RegisterVariable (&gl_skyclip);
7269         }
7270         Cvar_RegisterVariable(&r_motionblur);
7271         Cvar_RegisterVariable(&r_motionblur_maxblur);
7272         Cvar_RegisterVariable(&r_motionblur_bmin);
7273         Cvar_RegisterVariable(&r_motionblur_vmin);
7274         Cvar_RegisterVariable(&r_motionblur_vmax);
7275         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7276         Cvar_RegisterVariable(&r_motionblur_randomize);
7277         Cvar_RegisterVariable(&r_damageblur);
7278         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7279         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7280         Cvar_RegisterVariable(&r_equalize_entities_by);
7281         Cvar_RegisterVariable(&r_equalize_entities_to);
7282         Cvar_RegisterVariable(&r_depthfirst);
7283         Cvar_RegisterVariable(&r_useinfinitefarclip);
7284         Cvar_RegisterVariable(&r_farclip_base);
7285         Cvar_RegisterVariable(&r_farclip_world);
7286         Cvar_RegisterVariable(&r_nearclip);
7287         Cvar_RegisterVariable(&r_showbboxes);
7288         Cvar_RegisterVariable(&r_showsurfaces);
7289         Cvar_RegisterVariable(&r_showtris);
7290         Cvar_RegisterVariable(&r_shownormals);
7291         Cvar_RegisterVariable(&r_showlighting);
7292         Cvar_RegisterVariable(&r_showshadowvolumes);
7293         Cvar_RegisterVariable(&r_showcollisionbrushes);
7294         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7295         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7296         Cvar_RegisterVariable(&r_showdisabledepthtest);
7297         Cvar_RegisterVariable(&r_drawportals);
7298         Cvar_RegisterVariable(&r_drawentities);
7299         Cvar_RegisterVariable(&r_draw2d);
7300         Cvar_RegisterVariable(&r_drawworld);
7301         Cvar_RegisterVariable(&r_cullentities_trace);
7302         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7303         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7304         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7305         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7306         Cvar_RegisterVariable(&r_drawviewmodel);
7307         Cvar_RegisterVariable(&r_drawexteriormodel);
7308         Cvar_RegisterVariable(&r_speeds);
7309         Cvar_RegisterVariable(&r_fullbrights);
7310         Cvar_RegisterVariable(&r_wateralpha);
7311         Cvar_RegisterVariable(&r_dynamic);
7312         Cvar_RegisterVariable(&r_fakelight);
7313         Cvar_RegisterVariable(&r_fakelight_intensity);
7314         Cvar_RegisterVariable(&r_fullbright);
7315         Cvar_RegisterVariable(&r_shadows);
7316         Cvar_RegisterVariable(&r_shadows_darken);
7317         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7318         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7319         Cvar_RegisterVariable(&r_shadows_throwdistance);
7320         Cvar_RegisterVariable(&r_shadows_throwdirection);
7321         Cvar_RegisterVariable(&r_shadows_focus);
7322         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7323         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7324         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7325         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7326         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7327         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7328         Cvar_RegisterVariable(&r_fog_exp2);
7329         Cvar_RegisterVariable(&r_drawfog);
7330         Cvar_RegisterVariable(&r_transparentdepthmasking);
7331         Cvar_RegisterVariable(&r_texture_dds_load);
7332         Cvar_RegisterVariable(&r_texture_dds_save);
7333         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7334         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7335         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7336         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7337         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7338         Cvar_RegisterVariable(&r_textureunits);
7339         Cvar_RegisterVariable(&gl_combine);
7340         Cvar_RegisterVariable(&r_glsl);
7341         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7342         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7343         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7344         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7345         Cvar_RegisterVariable(&r_glsl_postprocess);
7346         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7347         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7348         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7349         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7350         Cvar_RegisterVariable(&r_water);
7351         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7352         Cvar_RegisterVariable(&r_water_clippingplanebias);
7353         Cvar_RegisterVariable(&r_water_refractdistort);
7354         Cvar_RegisterVariable(&r_water_reflectdistort);
7355         Cvar_RegisterVariable(&r_water_scissormode);
7356         Cvar_RegisterVariable(&r_lerpsprites);
7357         Cvar_RegisterVariable(&r_lerpmodels);
7358         Cvar_RegisterVariable(&r_lerplightstyles);
7359         Cvar_RegisterVariable(&r_waterscroll);
7360         Cvar_RegisterVariable(&r_bloom);
7361         Cvar_RegisterVariable(&r_bloom_colorscale);
7362         Cvar_RegisterVariable(&r_bloom_brighten);
7363         Cvar_RegisterVariable(&r_bloom_blur);
7364         Cvar_RegisterVariable(&r_bloom_resolution);
7365         Cvar_RegisterVariable(&r_bloom_colorexponent);
7366         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7367         Cvar_RegisterVariable(&r_hdr);
7368         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7369         Cvar_RegisterVariable(&r_hdr_glowintensity);
7370         Cvar_RegisterVariable(&r_hdr_range);
7371         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7372         Cvar_RegisterVariable(&developer_texturelogging);
7373         Cvar_RegisterVariable(&gl_lightmaps);
7374         Cvar_RegisterVariable(&r_test);
7375         Cvar_RegisterVariable(&r_glsl_saturation);
7376         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7377         Cvar_RegisterVariable(&r_framedatasize);
7378         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7379                 Cvar_SetValue("r_fullbrights", 0);
7380         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7381
7382         Cvar_RegisterVariable(&r_track_sprites);
7383         Cvar_RegisterVariable(&r_track_sprites_flags);
7384         Cvar_RegisterVariable(&r_track_sprites_scalew);
7385         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7386         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7387         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7388 }
7389
7390 extern void R_Textures_Init(void);
7391 extern void GL_Draw_Init(void);
7392 extern void GL_Main_Init(void);
7393 extern void R_Shadow_Init(void);
7394 extern void R_Sky_Init(void);
7395 extern void GL_Surf_Init(void);
7396 extern void R_Particles_Init(void);
7397 extern void R_Explosion_Init(void);
7398 extern void gl_backend_init(void);
7399 extern void Sbar_Init(void);
7400 extern void R_LightningBeams_Init(void);
7401 extern void Mod_RenderInit(void);
7402 extern void Font_Init(void);
7403
7404 void Render_Init(void)
7405 {
7406         gl_backend_init();
7407         R_Textures_Init();
7408         GL_Main_Init();
7409         Font_Init();
7410         GL_Draw_Init();
7411         R_Shadow_Init();
7412         R_Sky_Init();
7413         GL_Surf_Init();
7414         Sbar_Init();
7415         R_Particles_Init();
7416         R_Explosion_Init();
7417         R_LightningBeams_Init();
7418         Mod_RenderInit();
7419 }
7420
7421 /*
7422 ===============
7423 GL_Init
7424 ===============
7425 */
7426 extern char *ENGINE_EXTENSIONS;
7427 void GL_Init (void)
7428 {
7429         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7430         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7431         gl_version = (const char *)qglGetString(GL_VERSION);
7432         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7433
7434         if (!gl_extensions)
7435                 gl_extensions = "";
7436         if (!gl_platformextensions)
7437                 gl_platformextensions = "";
7438
7439         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7440         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7441         Con_Printf("GL_VERSION: %s\n", gl_version);
7442         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7443         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7444
7445         VID_CheckExtensions();
7446
7447         // LordHavoc: report supported extensions
7448         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7449
7450         // clear to black (loading plaque will be seen over this)
7451         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7452 }
7453
7454 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7455 {
7456         int i;
7457         mplane_t *p;
7458         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7459         {
7460                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7461                 if (i == 4)
7462                         continue;
7463                 p = r_refdef.view.frustum + i;
7464                 switch(p->signbits)
7465                 {
7466                 default:
7467                 case 0:
7468                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7469                                 return true;
7470                         break;
7471                 case 1:
7472                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7473                                 return true;
7474                         break;
7475                 case 2:
7476                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7477                                 return true;
7478                         break;
7479                 case 3:
7480                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7481                                 return true;
7482                         break;
7483                 case 4:
7484                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7485                                 return true;
7486                         break;
7487                 case 5:
7488                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7489                                 return true;
7490                         break;
7491                 case 6:
7492                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7493                                 return true;
7494                         break;
7495                 case 7:
7496                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7497                                 return true;
7498                         break;
7499                 }
7500         }
7501         return false;
7502 }
7503
7504 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7505 {
7506         int i;
7507         const mplane_t *p;
7508         for (i = 0;i < numplanes;i++)
7509         {
7510                 p = planes + i;
7511                 switch(p->signbits)
7512                 {
7513                 default:
7514                 case 0:
7515                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7516                                 return true;
7517                         break;
7518                 case 1:
7519                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7520                                 return true;
7521                         break;
7522                 case 2:
7523                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7524                                 return true;
7525                         break;
7526                 case 3:
7527                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7528                                 return true;
7529                         break;
7530                 case 4:
7531                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7532                                 return true;
7533                         break;
7534                 case 5:
7535                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7536                                 return true;
7537                         break;
7538                 case 6:
7539                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7540                                 return true;
7541                         break;
7542                 case 7:
7543                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7544                                 return true;
7545                         break;
7546                 }
7547         }
7548         return false;
7549 }
7550
7551 //==================================================================================
7552
7553 // LordHavoc: this stores temporary data used within the same frame
7554
7555 qboolean r_framedata_failed;
7556 static size_t r_framedata_size;
7557 static size_t r_framedata_current;
7558 static void *r_framedata_base;
7559
7560 void R_FrameData_Reset(void)
7561 {
7562         if (r_framedata_base)
7563                 Mem_Free(r_framedata_base);
7564         r_framedata_base = NULL;
7565         r_framedata_size = 0;
7566         r_framedata_current = 0;
7567         r_framedata_failed = false;
7568 }
7569
7570 void R_FrameData_NewFrame(void)
7571 {
7572         size_t wantedsize;
7573         if (r_framedata_failed)
7574                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7575         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7576         wantedsize = bound(65536, wantedsize, 128*1024*1024);
7577         if (r_framedata_size != wantedsize)
7578         {
7579                 r_framedata_size = wantedsize;
7580                 if (r_framedata_base)
7581                         Mem_Free(r_framedata_base);
7582                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7583         }
7584         r_framedata_current = 0;
7585         r_framedata_failed = false;
7586 }
7587
7588 void *R_FrameData_Alloc(size_t size)
7589 {
7590         void *data;
7591
7592         // align to 16 byte boundary
7593         size = (size + 15) & ~15;
7594         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7595         r_framedata_current += size;
7596
7597         // check overflow
7598         if (r_framedata_current > r_framedata_size)
7599                 r_framedata_failed = true;
7600
7601         // return NULL on everything after a failure
7602         if (r_framedata_failed)
7603                 return NULL;
7604
7605         return data;
7606 }
7607
7608 void *R_FrameData_Store(size_t size, void *data)
7609 {
7610         void *d = R_FrameData_Alloc(size);
7611         if (d)
7612                 memcpy(d, data, size);
7613         return d;
7614 }
7615
7616 //==================================================================================
7617
7618 // LordHavoc: animcache originally written by Echon, rewritten since then
7619
7620 /**
7621  * Animation cache prevents re-generating mesh data for an animated model
7622  * multiple times in one frame for lighting, shadowing, reflections, etc.
7623  */
7624
7625 void R_AnimCache_Free(void)
7626 {
7627 }
7628
7629 void R_AnimCache_ClearCache(void)
7630 {
7631         int i;
7632         entity_render_t *ent;
7633
7634         for (i = 0;i < r_refdef.scene.numentities;i++)
7635         {
7636                 ent = r_refdef.scene.entities[i];
7637                 ent->animcache_vertex3f = NULL;
7638                 ent->animcache_normal3f = NULL;
7639                 ent->animcache_svector3f = NULL;
7640                 ent->animcache_tvector3f = NULL;
7641                 ent->animcache_vertexposition = NULL;
7642                 ent->animcache_vertexmesh = NULL;
7643                 ent->animcache_vertexpositionbuffer = NULL;
7644                 ent->animcache_vertexmeshbuffer = NULL;
7645         }
7646 }
7647
7648 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7649 {
7650         int i;
7651
7652         // identical memory layout, so no need to allocate...
7653         // this also provides the vertexposition structure to everything, e.g.
7654         // depth masked rendering currently uses it even if having separate
7655         // arrays
7656         // NOTE: get rid of this optimization if changing it to e.g. 4f
7657         ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7658
7659         // TODO:
7660         // get rid of following uses of VERTEXPOSITION, change to the array:
7661         // R_DrawTextureSurfaceList_Sky if skyrendermasked
7662         // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7663         // R_DrawTextureSurfaceList_DepthOnly
7664         // R_Q1BSP_DrawShadowMap
7665
7666         switch(vid.renderpath)
7667         {
7668         case RENDERPATH_GL20:
7669         case RENDERPATH_CGGL:
7670                 // need the meshbuffers if !gl_mesh_separatearrays.integer
7671                 if (gl_mesh_separatearrays.integer)
7672                         return;
7673                 break;
7674         case RENDERPATH_D3D9:
7675         case RENDERPATH_D3D10:
7676         case RENDERPATH_D3D11:
7677                 // always need the meshbuffers
7678                 break;
7679         case RENDERPATH_GL13:
7680         case RENDERPATH_GL11:
7681                 // never need the meshbuffers
7682                 return;
7683         }
7684
7685         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7686                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7687         /*
7688         if (!ent->animcache_vertexposition)
7689                 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7690         */
7691         if (ent->animcache_vertexposition)
7692         {
7693                 /*
7694                 for (i = 0;i < numvertices;i++)
7695                         memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7696                 */
7697                 // TODO: upload vertex buffer?
7698         }
7699         if (ent->animcache_vertexmesh)
7700         {
7701                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7702                 for (i = 0;i < numvertices;i++)
7703                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7704                 if (ent->animcache_svector3f)
7705                         for (i = 0;i < numvertices;i++)
7706                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7707                 if (ent->animcache_tvector3f)
7708                         for (i = 0;i < numvertices;i++)
7709                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7710                 if (ent->animcache_normal3f)
7711                         for (i = 0;i < numvertices;i++)
7712                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7713                 // TODO: upload vertex buffer?
7714         }
7715 }
7716
7717 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7718 {
7719         dp_model_t *model = ent->model;
7720         int numvertices;
7721         // see if it's already cached this frame
7722         if (ent->animcache_vertex3f)
7723         {
7724                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7725                 if (wantnormals || wanttangents)
7726                 {
7727                         if (ent->animcache_normal3f)
7728                                 wantnormals = false;
7729                         if (ent->animcache_svector3f)
7730                                 wanttangents = false;
7731                         if (wantnormals || wanttangents)
7732                         {
7733                                 numvertices = model->surfmesh.num_vertices;
7734                                 if (wantnormals)
7735                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7736                                 if (wanttangents)
7737                                 {
7738                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7739                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7740                                 }
7741                                 if (!r_framedata_failed)
7742                                 {
7743                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7744                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7745                                 }
7746                         }
7747                 }
7748         }
7749         else
7750         {
7751                 // see if this ent is worth caching
7752                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7753                         return false;
7754                 // get some memory for this entity and generate mesh data
7755                 numvertices = model->surfmesh.num_vertices;
7756                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7757                 if (wantnormals)
7758                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7759                 if (wanttangents)
7760                 {
7761                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7762                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7763                 }
7764                 if (!r_framedata_failed)
7765                 {
7766                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7767                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7768                 }
7769         }
7770         return !r_framedata_failed;
7771 }
7772
7773 void R_AnimCache_CacheVisibleEntities(void)
7774 {
7775         int i;
7776         qboolean wantnormals = true;
7777         qboolean wanttangents = !r_showsurfaces.integer;
7778
7779         switch(vid.renderpath)
7780         {
7781         case RENDERPATH_GL20:
7782         case RENDERPATH_CGGL:
7783         case RENDERPATH_D3D9:
7784         case RENDERPATH_D3D10:
7785         case RENDERPATH_D3D11:
7786                 break;
7787         case RENDERPATH_GL13:
7788         case RENDERPATH_GL11:
7789                 wanttangents = false;
7790                 break;
7791         }
7792
7793         if (r_shownormals.integer)
7794                 wanttangents = wantnormals = true;
7795
7796         // TODO: thread this
7797         // NOTE: R_PrepareRTLights() also caches entities
7798
7799         for (i = 0;i < r_refdef.scene.numentities;i++)
7800                 if (r_refdef.viewcache.entityvisible[i])
7801                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7802 }
7803
7804 //==================================================================================
7805
7806 static void R_View_UpdateEntityLighting (void)
7807 {
7808         int i;
7809         entity_render_t *ent;
7810         vec3_t tempdiffusenormal, avg;
7811         vec_t f, fa, fd, fdd;
7812         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7813
7814         for (i = 0;i < r_refdef.scene.numentities;i++)
7815         {
7816                 ent = r_refdef.scene.entities[i];
7817
7818                 // skip unseen models
7819                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7820                         continue;
7821
7822                 // skip bsp models
7823                 if (ent->model && ent->model->brush.num_leafs)
7824                 {
7825                         // TODO: use modellight for r_ambient settings on world?
7826                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7827                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7828                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7829                         continue;
7830                 }
7831
7832                 // fetch the lighting from the worldmodel data
7833                 VectorClear(ent->modellight_ambient);
7834                 VectorClear(ent->modellight_diffuse);
7835                 VectorClear(tempdiffusenormal);
7836                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7837                 {
7838                         vec3_t org;
7839                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7840                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7841                         if(ent->flags & RENDER_EQUALIZE)
7842                         {
7843                                 // first fix up ambient lighting...
7844                                 if(r_equalize_entities_minambient.value > 0)
7845                                 {
7846                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7847                                         if(fd > 0)
7848                                         {
7849                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7850                                                 if(fa < r_equalize_entities_minambient.value * fd)
7851                                                 {
7852                                                         // solve:
7853                                                         //   fa'/fd' = minambient
7854                                                         //   fa'+0.25*fd' = fa+0.25*fd
7855                                                         //   ...
7856                                                         //   fa' = fd' * minambient
7857                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7858                                                         //   ...
7859                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7860                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7861                                                         //   ...
7862                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7863                                                         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
7864                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7865                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7866                                                 }
7867                                         }
7868                                 }
7869
7870                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7871                                 {
7872                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7873                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7874                                         if(f > 0)
7875                                         {
7876                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7877                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7878                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7879                                         }
7880                                 }
7881                         }
7882                 }
7883                 else // highly rare
7884                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7885
7886                 // move the light direction into modelspace coordinates for lighting code
7887                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7888                 if(VectorLength2(ent->modellight_lightdir) == 0)
7889                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7890                 VectorNormalize(ent->modellight_lightdir);
7891         }
7892 }
7893
7894 #define MAX_LINEOFSIGHTTRACES 64
7895
7896 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7897 {
7898         int i;
7899         vec3_t boxmins, boxmaxs;
7900         vec3_t start;
7901         vec3_t end;
7902         dp_model_t *model = r_refdef.scene.worldmodel;
7903
7904         if (!model || !model->brush.TraceLineOfSight)
7905                 return true;
7906
7907         // expand the box a little
7908         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7909         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7910         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7911         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7912         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7913         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7914
7915         // return true if eye is inside enlarged box
7916         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7917                 return true;
7918
7919         // try center
7920         VectorCopy(eye, start);
7921         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7922         if (model->brush.TraceLineOfSight(model, start, end))
7923                 return true;
7924
7925         // try various random positions
7926         for (i = 0;i < numsamples;i++)
7927         {
7928                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7929                 if (model->brush.TraceLineOfSight(model, start, end))
7930                         return true;
7931         }
7932
7933         return false;
7934 }
7935
7936
7937 static void R_View_UpdateEntityVisible (void)
7938 {
7939         int i;
7940         int renderimask;
7941         int samples;
7942         entity_render_t *ent;
7943
7944         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7945                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7946                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
7947                 :                                                          RENDER_EXTERIORMODEL;
7948         if (!r_drawviewmodel.integer)
7949                 renderimask |= RENDER_VIEWMODEL;
7950         if (!r_drawexteriormodel.integer)
7951                 renderimask |= RENDER_EXTERIORMODEL;
7952         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7953         {
7954                 // worldmodel can check visibility
7955                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7956                 for (i = 0;i < r_refdef.scene.numentities;i++)
7957                 {
7958                         ent = r_refdef.scene.entities[i];
7959                         if (!(ent->flags & renderimask))
7960                         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)))
7961                         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))
7962                                 r_refdef.viewcache.entityvisible[i] = true;
7963                 }
7964                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7965                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7966                 {
7967                         for (i = 0;i < r_refdef.scene.numentities;i++)
7968                         {
7969                                 ent = r_refdef.scene.entities[i];
7970                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7971                                 {
7972                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7973                                         if (samples < 0)
7974                                                 continue; // temp entities do pvs only
7975                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7976                                                 ent->last_trace_visibility = realtime;
7977                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7978                                                 r_refdef.viewcache.entityvisible[i] = 0;
7979                                 }
7980                         }
7981                 }
7982         }
7983         else
7984         {
7985                 // no worldmodel or it can't check visibility
7986                 for (i = 0;i < r_refdef.scene.numentities;i++)
7987                 {
7988                         ent = r_refdef.scene.entities[i];
7989                         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));
7990                 }
7991         }
7992 }
7993
7994 /// only used if skyrendermasked, and normally returns false
7995 int R_DrawBrushModelsSky (void)
7996 {
7997         int i, sky;
7998         entity_render_t *ent;
7999
8000         sky = false;
8001         for (i = 0;i < r_refdef.scene.numentities;i++)
8002         {
8003                 if (!r_refdef.viewcache.entityvisible[i])
8004                         continue;
8005                 ent = r_refdef.scene.entities[i];
8006                 if (!ent->model || !ent->model->DrawSky)
8007                         continue;
8008                 ent->model->DrawSky(ent);
8009                 sky = true;
8010         }
8011         return sky;
8012 }
8013
8014 static void R_DrawNoModel(entity_render_t *ent);
8015 static void R_DrawModels(void)
8016 {
8017         int i;
8018         entity_render_t *ent;
8019
8020         for (i = 0;i < r_refdef.scene.numentities;i++)
8021         {
8022                 if (!r_refdef.viewcache.entityvisible[i])
8023                         continue;
8024                 ent = r_refdef.scene.entities[i];
8025                 r_refdef.stats.entities++;
8026                 if (ent->model && ent->model->Draw != NULL)
8027                         ent->model->Draw(ent);
8028                 else
8029                         R_DrawNoModel(ent);
8030         }
8031 }
8032
8033 static void R_DrawModelsDepth(void)
8034 {
8035         int i;
8036         entity_render_t *ent;
8037
8038         for (i = 0;i < r_refdef.scene.numentities;i++)
8039         {
8040                 if (!r_refdef.viewcache.entityvisible[i])
8041                         continue;
8042                 ent = r_refdef.scene.entities[i];
8043                 if (ent->model && ent->model->DrawDepth != NULL)
8044                         ent->model->DrawDepth(ent);
8045         }
8046 }
8047
8048 static void R_DrawModelsDebug(void)
8049 {
8050         int i;
8051         entity_render_t *ent;
8052
8053         for (i = 0;i < r_refdef.scene.numentities;i++)
8054         {
8055                 if (!r_refdef.viewcache.entityvisible[i])
8056                         continue;
8057                 ent = r_refdef.scene.entities[i];
8058                 if (ent->model && ent->model->DrawDebug != NULL)
8059                         ent->model->DrawDebug(ent);
8060         }
8061 }
8062
8063 static void R_DrawModelsAddWaterPlanes(void)
8064 {
8065         int i;
8066         entity_render_t *ent;
8067
8068         for (i = 0;i < r_refdef.scene.numentities;i++)
8069         {
8070                 if (!r_refdef.viewcache.entityvisible[i])
8071                         continue;
8072                 ent = r_refdef.scene.entities[i];
8073                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8074                         ent->model->DrawAddWaterPlanes(ent);
8075         }
8076 }
8077
8078 static void R_View_SetFrustum(const int *scissor)
8079 {
8080         int i;
8081         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8082         vec3_t forward, left, up, origin, v;
8083
8084         if(scissor)
8085         {
8086                 // flipped x coordinates (because x points left here)
8087                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8088                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8089
8090                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8091                 switch(vid.renderpath)
8092                 {
8093                         case RENDERPATH_D3D9:
8094                         case RENDERPATH_D3D10:
8095                         case RENDERPATH_D3D11:
8096                                 // non-flipped y coordinates
8097                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8098                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8099                                 break;
8100                         case RENDERPATH_GL11:
8101                         case RENDERPATH_GL13:
8102                         case RENDERPATH_GL20:
8103                         case RENDERPATH_CGGL:
8104                                 // non-flipped y coordinates
8105                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8106                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8107                                 break;
8108                 }
8109         }
8110
8111         // we can't trust r_refdef.view.forward and friends in reflected scenes
8112         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8113
8114 #if 0
8115         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8116         r_refdef.view.frustum[0].normal[1] = 0 - 0;
8117         r_refdef.view.frustum[0].normal[2] = -1 - 0;
8118         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8119         r_refdef.view.frustum[1].normal[1] = 0 + 0;
8120         r_refdef.view.frustum[1].normal[2] = -1 + 0;
8121         r_refdef.view.frustum[2].normal[0] = 0 - 0;
8122         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8123         r_refdef.view.frustum[2].normal[2] = -1 - 0;
8124         r_refdef.view.frustum[3].normal[0] = 0 + 0;
8125         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8126         r_refdef.view.frustum[3].normal[2] = -1 + 0;
8127 #endif
8128
8129 #if 0
8130         zNear = r_refdef.nearclip;
8131         nudge = 1.0 - 1.0 / (1<<23);
8132         r_refdef.view.frustum[4].normal[0] = 0 - 0;
8133         r_refdef.view.frustum[4].normal[1] = 0 - 0;
8134         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8135         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8136         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8137         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8138         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8139         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8140 #endif
8141
8142
8143
8144 #if 0
8145         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8146         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8147         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8148         r_refdef.view.frustum[0].dist = m[15] - m[12];
8149
8150         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8151         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8152         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8153         r_refdef.view.frustum[1].dist = m[15] + m[12];
8154
8155         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8156         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8157         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8158         r_refdef.view.frustum[2].dist = m[15] - m[13];
8159
8160         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8161         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8162         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8163         r_refdef.view.frustum[3].dist = m[15] + m[13];
8164
8165         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8166         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8167         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8168         r_refdef.view.frustum[4].dist = m[15] - m[14];
8169
8170         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8171         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8172         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8173         r_refdef.view.frustum[5].dist = m[15] + m[14];
8174 #endif
8175
8176         if (r_refdef.view.useperspective)
8177         {
8178                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8179                 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]);
8180                 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]);
8181                 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]);
8182                 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]);
8183
8184                 // then the normals from the corners relative to origin
8185                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8186                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8187                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8188                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8189
8190                 // in a NORMAL view, forward cross left == up
8191                 // in a REFLECTED view, forward cross left == down
8192                 // so our cross products above need to be adjusted for a left handed coordinate system
8193                 CrossProduct(forward, left, v);
8194                 if(DotProduct(v, up) < 0)
8195                 {
8196                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8197                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8198                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8199                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8200                 }
8201
8202                 // Leaving those out was a mistake, those were in the old code, and they
8203                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8204                 // I couldn't reproduce it after adding those normalizations. --blub
8205                 VectorNormalize(r_refdef.view.frustum[0].normal);
8206                 VectorNormalize(r_refdef.view.frustum[1].normal);
8207                 VectorNormalize(r_refdef.view.frustum[2].normal);
8208                 VectorNormalize(r_refdef.view.frustum[3].normal);
8209
8210                 // make the corners absolute
8211                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8212                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8213                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8214                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8215
8216                 // one more normal
8217                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8218
8219                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8220                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8221                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8222                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8223                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8224         }
8225         else
8226         {
8227                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8228                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8229                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8230                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8231                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8232                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8233                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8234                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8235                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8236                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8237         }
8238         r_refdef.view.numfrustumplanes = 5;
8239
8240         if (r_refdef.view.useclipplane)
8241         {
8242                 r_refdef.view.numfrustumplanes = 6;
8243                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8244         }
8245
8246         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8247                 PlaneClassify(r_refdef.view.frustum + i);
8248
8249         // LordHavoc: note to all quake engine coders, Quake had a special case
8250         // for 90 degrees which assumed a square view (wrong), so I removed it,
8251         // Quake2 has it disabled as well.
8252
8253         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8254         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8255         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8256         //PlaneClassify(&frustum[0]);
8257
8258         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8259         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8260         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8261         //PlaneClassify(&frustum[1]);
8262
8263         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8264         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8265         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8266         //PlaneClassify(&frustum[2]);
8267
8268         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8269         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8270         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8271         //PlaneClassify(&frustum[3]);
8272
8273         // nearclip plane
8274         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8275         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8276         //PlaneClassify(&frustum[4]);
8277 }
8278
8279 void R_View_UpdateWithScissor(const int *myscissor)
8280 {
8281         R_Main_ResizeViewCache();
8282         R_View_SetFrustum(myscissor);
8283         R_View_WorldVisibility(r_refdef.view.useclipplane);
8284         R_View_UpdateEntityVisible();
8285         R_View_UpdateEntityLighting();
8286 }
8287
8288 void R_View_Update(void)
8289 {
8290         R_Main_ResizeViewCache();
8291         R_View_SetFrustum(NULL);
8292         R_View_WorldVisibility(r_refdef.view.useclipplane);
8293         R_View_UpdateEntityVisible();
8294         R_View_UpdateEntityLighting();
8295 }
8296
8297 void R_SetupView(qboolean allowwaterclippingplane)
8298 {
8299         const float *customclipplane = NULL;
8300         float plane[4];
8301         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8302         {
8303                 // LordHavoc: couldn't figure out how to make this approach the
8304                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8305                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8306                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8307                         dist = r_refdef.view.clipplane.dist;
8308                 plane[0] = r_refdef.view.clipplane.normal[0];
8309                 plane[1] = r_refdef.view.clipplane.normal[1];
8310                 plane[2] = r_refdef.view.clipplane.normal[2];
8311                 plane[3] = dist;
8312                 customclipplane = plane;
8313         }
8314
8315         if (!r_refdef.view.useperspective)
8316                 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);
8317         else if (vid.stencil && r_useinfinitefarclip.integer)
8318                 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);
8319         else
8320                 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);
8321         R_SetViewport(&r_refdef.view.viewport);
8322 }
8323
8324 void R_EntityMatrix(const matrix4x4_t *matrix)
8325 {
8326         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8327         {
8328                 gl_modelmatrixchanged = false;
8329                 gl_modelmatrix = *matrix;
8330                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8331                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8332                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8333                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8334                 CHECKGLERROR
8335                 switch(vid.renderpath)
8336                 {
8337                 case RENDERPATH_D3D9:
8338 #ifdef SUPPORTD3D
8339                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8340                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8341 #endif
8342                         break;
8343                 case RENDERPATH_D3D10:
8344                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8345                         break;
8346                 case RENDERPATH_D3D11:
8347                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8348                         break;
8349                 case RENDERPATH_GL20:
8350                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8351                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8352                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8353                         break;
8354                 case RENDERPATH_CGGL:
8355 #ifdef SUPPORTCG
8356                         CHECKCGERROR
8357                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8358                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8359                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8360 #endif
8361                         break;
8362                 case RENDERPATH_GL13:
8363                 case RENDERPATH_GL11:
8364                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8365                         break;
8366                 }
8367         }
8368 }
8369
8370 void R_ResetViewRendering2D(void)
8371 {
8372         r_viewport_t viewport;
8373         DrawQ_Finish();
8374
8375         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8376         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);
8377         R_SetViewport(&viewport);
8378         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8379         GL_Color(1, 1, 1, 1);
8380         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8381         GL_BlendFunc(GL_ONE, GL_ZERO);
8382         GL_AlphaTest(false);
8383         GL_ScissorTest(false);
8384         GL_DepthMask(false);
8385         GL_DepthRange(0, 1);
8386         GL_DepthTest(false);
8387         GL_DepthFunc(GL_LEQUAL);
8388         R_EntityMatrix(&identitymatrix);
8389         R_Mesh_ResetTextureState();
8390         GL_PolygonOffset(0, 0);
8391         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8392         switch(vid.renderpath)
8393         {
8394         case RENDERPATH_GL11:
8395         case RENDERPATH_GL13:
8396         case RENDERPATH_GL20:
8397         case RENDERPATH_CGGL:
8398                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8399                 break;
8400         case RENDERPATH_D3D9:
8401         case RENDERPATH_D3D10:
8402         case RENDERPATH_D3D11:
8403                 break;
8404         }
8405         GL_CullFace(GL_NONE);
8406 }
8407
8408 void R_ResetViewRendering3D(void)
8409 {
8410         DrawQ_Finish();
8411
8412         R_SetupView(true);
8413         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8414         GL_Color(1, 1, 1, 1);
8415         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8416         GL_BlendFunc(GL_ONE, GL_ZERO);
8417         GL_AlphaTest(false);
8418         GL_ScissorTest(true);
8419         GL_DepthMask(true);
8420         GL_DepthRange(0, 1);
8421         GL_DepthTest(true);
8422         GL_DepthFunc(GL_LEQUAL);
8423         R_EntityMatrix(&identitymatrix);
8424         R_Mesh_ResetTextureState();
8425         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8426         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8427         switch(vid.renderpath)
8428         {
8429         case RENDERPATH_GL11:
8430         case RENDERPATH_GL13:
8431         case RENDERPATH_GL20:
8432         case RENDERPATH_CGGL:
8433                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8434                 break;
8435         case RENDERPATH_D3D9:
8436         case RENDERPATH_D3D10:
8437         case RENDERPATH_D3D11:
8438                 break;
8439         }
8440         GL_CullFace(r_refdef.view.cullface_back);
8441 }
8442
8443 /*
8444 ================
8445 R_RenderView_UpdateViewVectors
8446 ================
8447 */
8448 static void R_RenderView_UpdateViewVectors(void)
8449 {
8450         // break apart the view matrix into vectors for various purposes
8451         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8452         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8453         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8454         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8455         // make an inverted copy of the view matrix for tracking sprites
8456         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8457 }
8458
8459 void R_RenderScene(void);
8460 void R_RenderWaterPlanes(void);
8461
8462 static void R_Water_StartFrame(void)
8463 {
8464         int i;
8465         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8466         r_waterstate_waterplane_t *p;
8467
8468         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8469                 return;
8470
8471         switch(vid.renderpath)
8472         {
8473         case RENDERPATH_GL20:
8474         case RENDERPATH_CGGL:
8475         case RENDERPATH_D3D9:
8476         case RENDERPATH_D3D10:
8477         case RENDERPATH_D3D11:
8478                 break;
8479         case RENDERPATH_GL13:
8480         case RENDERPATH_GL11:
8481                 return;
8482         }
8483
8484         // set waterwidth and waterheight to the water resolution that will be
8485         // used (often less than the screen resolution for faster rendering)
8486         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8487         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8488
8489         // calculate desired texture sizes
8490         // can't use water if the card does not support the texture size
8491         if (!r_water.integer || r_showsurfaces.integer)
8492                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8493         else if (vid.support.arb_texture_non_power_of_two)
8494         {
8495                 texturewidth = waterwidth;
8496                 textureheight = waterheight;
8497                 camerawidth = waterwidth;
8498                 cameraheight = waterheight;
8499         }
8500         else
8501         {
8502                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8503                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8504                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8505                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8506         }
8507
8508         // allocate textures as needed
8509         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8510         {
8511                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8512                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8513                 {
8514                         if (p->texture_refraction)
8515                                 R_FreeTexture(p->texture_refraction);
8516                         p->texture_refraction = NULL;
8517                         if (p->texture_reflection)
8518                                 R_FreeTexture(p->texture_reflection);
8519                         p->texture_reflection = NULL;
8520                         if (p->texture_camera)
8521                                 R_FreeTexture(p->texture_camera);
8522                         p->texture_camera = NULL;
8523                 }
8524                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8525                 r_waterstate.texturewidth = texturewidth;
8526                 r_waterstate.textureheight = textureheight;
8527                 r_waterstate.camerawidth = camerawidth;
8528                 r_waterstate.cameraheight = cameraheight;
8529         }
8530
8531         if (r_waterstate.texturewidth)
8532         {
8533                 r_waterstate.enabled = true;
8534
8535                 // when doing a reduced render (HDR) we want to use a smaller area
8536                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8537                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8538
8539                 // set up variables that will be used in shader setup
8540                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8541                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8542                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8543                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8544         }
8545
8546         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8547         r_waterstate.numwaterplanes = 0;
8548 }
8549
8550 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8551 {
8552         int triangleindex, planeindex;
8553         const int *e;
8554         vec3_t vert[3];
8555         vec3_t normal;
8556         vec3_t center;
8557         mplane_t plane;
8558         r_waterstate_waterplane_t *p;
8559         texture_t *t = R_GetCurrentTexture(surface->texture);
8560
8561         // just use the first triangle with a valid normal for any decisions
8562         VectorClear(normal);
8563         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8564         {
8565                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8566                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8567                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8568                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8569                 if (VectorLength2(normal) >= 0.001)
8570                         break;
8571         }
8572
8573         VectorCopy(normal, plane.normal);
8574         VectorNormalize(plane.normal);
8575         plane.dist = DotProduct(vert[0], plane.normal);
8576         PlaneClassify(&plane);
8577         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8578         {
8579                 // skip backfaces (except if nocullface is set)
8580                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8581                         return;
8582                 VectorNegate(plane.normal, plane.normal);
8583                 plane.dist *= -1;
8584                 PlaneClassify(&plane);
8585         }
8586
8587
8588         // find a matching plane if there is one
8589         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8590                 if(p->camera_entity == t->camera_entity)
8591                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8592                                 break;
8593         if (planeindex >= r_waterstate.maxwaterplanes)
8594                 return; // nothing we can do, out of planes
8595
8596         // if this triangle does not fit any known plane rendered this frame, add one
8597         if (planeindex >= r_waterstate.numwaterplanes)
8598         {
8599                 // store the new plane
8600                 r_waterstate.numwaterplanes++;
8601                 p->plane = plane;
8602                 // clear materialflags and pvs
8603                 p->materialflags = 0;
8604                 p->pvsvalid = false;
8605                 p->camera_entity = t->camera_entity;
8606                 VectorCopy(surface->mins, p->mins);
8607                 VectorCopy(surface->maxs, p->maxs);
8608         }
8609         else
8610         {
8611                 // merge mins/maxs
8612                 p->mins[0] = min(p->mins[0], surface->mins[0]);
8613                 p->mins[1] = min(p->mins[1], surface->mins[1]);
8614                 p->mins[2] = min(p->mins[2], surface->mins[2]);
8615                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8616                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8617                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8618         }
8619         // merge this surface's materialflags into the waterplane
8620         p->materialflags |= t->currentmaterialflags;
8621         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8622         {
8623                 // merge this surface's PVS into the waterplane
8624                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8625                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8626                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8627                 {
8628                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8629                         p->pvsvalid = true;
8630                 }
8631         }
8632 }
8633
8634 static void R_Water_ProcessPlanes(void)
8635 {
8636         int myscissor[4];
8637         r_refdef_view_t originalview;
8638         r_refdef_view_t myview;
8639         int planeindex;
8640         r_waterstate_waterplane_t *p;
8641         vec3_t visorigin;
8642
8643         originalview = r_refdef.view;
8644
8645         // make sure enough textures are allocated
8646         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8647         {
8648                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8649                 {
8650                         if (!p->texture_refraction)
8651                                 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);
8652                         if (!p->texture_refraction)
8653                                 goto error;
8654                 }
8655                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8656                 {
8657                         if (!p->texture_camera)
8658                                 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);
8659                         if (!p->texture_camera)
8660                                 goto error;
8661                 }
8662
8663                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8664                 {
8665                         if (!p->texture_reflection)
8666                                 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);
8667                         if (!p->texture_reflection)
8668                                 goto error;
8669                 }
8670         }
8671
8672         // render views
8673         r_refdef.view = originalview;
8674         r_refdef.view.showdebug = false;
8675         r_refdef.view.width = r_waterstate.waterwidth;
8676         r_refdef.view.height = r_waterstate.waterheight;
8677         r_refdef.view.useclipplane = true;
8678         myview = r_refdef.view;
8679         r_waterstate.renderingscene = true;
8680         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8681         {
8682                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8683                 {
8684                         r_refdef.view = myview;
8685                         if(r_water_scissormode.integer)
8686                         {
8687                                 R_SetupView(true);
8688                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8689                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8690                         }
8691
8692                         // render reflected scene and copy into texture
8693                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8694                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8695                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8696                         r_refdef.view.clipplane = p->plane;
8697
8698                         // reverse the cullface settings for this render
8699                         r_refdef.view.cullface_front = GL_FRONT;
8700                         r_refdef.view.cullface_back = GL_BACK;
8701                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8702                         {
8703                                 r_refdef.view.usecustompvs = true;
8704                                 if (p->pvsvalid)
8705                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8706                                 else
8707                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8708                         }
8709
8710                         R_ResetViewRendering3D();
8711                         R_ClearScreen(r_refdef.fogenabled);
8712                         if(r_water_scissormode.integer & 2)
8713                                 R_View_UpdateWithScissor(myscissor);
8714                         else
8715                                 R_View_Update();
8716                         if(r_water_scissormode.integer & 1)
8717                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8718                         R_RenderScene();
8719
8720                         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);
8721                 }
8722
8723                 // render the normal view scene and copy into texture
8724                 // (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)
8725                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8726                 {
8727                         r_refdef.view = myview;
8728                         if(r_water_scissormode.integer)
8729                         {
8730                                 R_SetupView(true);
8731                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8732                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8733                         }
8734
8735                         r_waterstate.renderingrefraction = true;
8736
8737                         r_refdef.view.clipplane = p->plane;
8738                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8739                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8740
8741                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8742                         {
8743                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8744                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8745                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8746                                 R_RenderView_UpdateViewVectors();
8747                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8748                                 {
8749                                         r_refdef.view.usecustompvs = true;
8750                                         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);
8751                                 }
8752                         }
8753
8754                         PlaneClassify(&r_refdef.view.clipplane);
8755
8756                         R_ResetViewRendering3D();
8757                         R_ClearScreen(r_refdef.fogenabled);
8758                         if(r_water_scissormode.integer & 2)
8759                                 R_View_UpdateWithScissor(myscissor);
8760                         else
8761                                 R_View_Update();
8762                         if(r_water_scissormode.integer & 1)
8763                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8764                         R_RenderScene();
8765
8766                         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);
8767                         r_waterstate.renderingrefraction = false;
8768                 }
8769                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8770                 {
8771                         r_refdef.view = myview;
8772
8773                         r_refdef.view.clipplane = p->plane;
8774                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8775                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8776
8777                         r_refdef.view.width = r_waterstate.camerawidth;
8778                         r_refdef.view.height = r_waterstate.cameraheight;
8779                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8780                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8781
8782                         if(p->camera_entity)
8783                         {
8784                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8785                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8786                         }
8787
8788                         // note: all of the view is used for displaying... so
8789                         // there is no use in scissoring
8790
8791                         // reverse the cullface settings for this render
8792                         r_refdef.view.cullface_front = GL_FRONT;
8793                         r_refdef.view.cullface_back = GL_BACK;
8794                         // also reverse the view matrix
8795                         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
8796                         R_RenderView_UpdateViewVectors();
8797                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8798                         {
8799                                 r_refdef.view.usecustompvs = true;
8800                                 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);
8801                         }
8802                         
8803                         // camera needs no clipplane
8804                         r_refdef.view.useclipplane = false;
8805
8806                         PlaneClassify(&r_refdef.view.clipplane);
8807
8808                         R_ResetViewRendering3D();
8809                         R_ClearScreen(r_refdef.fogenabled);
8810                         R_View_Update();
8811                         R_RenderScene();
8812
8813                         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);
8814                         r_waterstate.renderingrefraction = false;
8815                 }
8816
8817         }
8818         r_waterstate.renderingscene = false;
8819         r_refdef.view = originalview;
8820         R_ResetViewRendering3D();
8821         R_ClearScreen(r_refdef.fogenabled);
8822         R_View_Update();
8823         return;
8824 error:
8825         r_refdef.view = originalview;
8826         r_waterstate.renderingscene = false;
8827         Cvar_SetValueQuick(&r_water, 0);
8828         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8829         return;
8830 }
8831
8832 void R_Bloom_StartFrame(void)
8833 {
8834         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8835
8836         switch(vid.renderpath)
8837         {
8838         case RENDERPATH_GL20:
8839         case RENDERPATH_CGGL:
8840         case RENDERPATH_D3D9:
8841         case RENDERPATH_D3D10:
8842         case RENDERPATH_D3D11:
8843                 break;
8844         case RENDERPATH_GL13:
8845         case RENDERPATH_GL11:
8846                 return;
8847         }
8848
8849         // set bloomwidth and bloomheight to the bloom resolution that will be
8850         // used (often less than the screen resolution for faster rendering)
8851         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8852         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8853         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8854         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8855         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8856
8857         // calculate desired texture sizes
8858         if (vid.support.arb_texture_non_power_of_two)
8859         {
8860                 screentexturewidth = r_refdef.view.width;
8861                 screentextureheight = r_refdef.view.height;
8862                 bloomtexturewidth = r_bloomstate.bloomwidth;
8863                 bloomtextureheight = r_bloomstate.bloomheight;
8864         }
8865         else
8866         {
8867                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8868                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8869                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8870                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8871         }
8872
8873         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))
8874         {
8875                 Cvar_SetValueQuick(&r_hdr, 0);
8876                 Cvar_SetValueQuick(&r_bloom, 0);
8877                 Cvar_SetValueQuick(&r_motionblur, 0);
8878                 Cvar_SetValueQuick(&r_damageblur, 0);
8879         }
8880
8881         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)))
8882                 screentexturewidth = screentextureheight = 0;
8883         if (!r_hdr.integer && !r_bloom.integer)
8884                 bloomtexturewidth = bloomtextureheight = 0;
8885
8886         // allocate textures as needed
8887         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8888         {
8889                 if (r_bloomstate.texture_screen)
8890                         R_FreeTexture(r_bloomstate.texture_screen);
8891                 r_bloomstate.texture_screen = NULL;
8892                 r_bloomstate.screentexturewidth = screentexturewidth;
8893                 r_bloomstate.screentextureheight = screentextureheight;
8894                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8895                         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);
8896         }
8897         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8898         {
8899                 if (r_bloomstate.texture_bloom)
8900                         R_FreeTexture(r_bloomstate.texture_bloom);
8901                 r_bloomstate.texture_bloom = NULL;
8902                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8903                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8904                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8905                         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);
8906         }
8907
8908         // when doing a reduced render (HDR) we want to use a smaller area
8909         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8910         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8911         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8912         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8913         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8914
8915         // set up a texcoord array for the full resolution screen image
8916         // (we have to keep this around to copy back during final render)
8917         r_bloomstate.screentexcoord2f[0] = 0;
8918         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8919         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8920         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8921         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8922         r_bloomstate.screentexcoord2f[5] = 0;
8923         r_bloomstate.screentexcoord2f[6] = 0;
8924         r_bloomstate.screentexcoord2f[7] = 0;
8925
8926         // set up a texcoord array for the reduced resolution bloom image
8927         // (which will be additive blended over the screen image)
8928         r_bloomstate.bloomtexcoord2f[0] = 0;
8929         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8930         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8931         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8932         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8933         r_bloomstate.bloomtexcoord2f[5] = 0;
8934         r_bloomstate.bloomtexcoord2f[6] = 0;
8935         r_bloomstate.bloomtexcoord2f[7] = 0;
8936
8937         switch(vid.renderpath)
8938         {
8939         case RENDERPATH_GL11:
8940         case RENDERPATH_GL13:
8941         case RENDERPATH_GL20:
8942         case RENDERPATH_CGGL:
8943                 break;
8944         case RENDERPATH_D3D9:
8945         case RENDERPATH_D3D10:
8946         case RENDERPATH_D3D11:
8947                 {
8948                         int i;
8949                         for (i = 0;i < 4;i++)
8950                         {
8951                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8952                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8953                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8954                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8955                         }
8956                 }
8957                 break;
8958         }
8959
8960         if (r_hdr.integer || r_bloom.integer)
8961         {
8962                 r_bloomstate.enabled = true;
8963                 r_bloomstate.hdr = r_hdr.integer != 0;
8964         }
8965
8966         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);
8967 }
8968
8969 void R_Bloom_CopyBloomTexture(float colorscale)
8970 {
8971         r_refdef.stats.bloom++;
8972
8973         // scale down screen texture to the bloom texture size
8974         CHECKGLERROR
8975         R_SetViewport(&r_bloomstate.viewport);
8976         GL_BlendFunc(GL_ONE, GL_ZERO);
8977         GL_Color(colorscale, colorscale, colorscale, 1);
8978         // 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...
8979         switch(vid.renderpath)
8980         {
8981         case RENDERPATH_GL11:
8982         case RENDERPATH_GL13:
8983         case RENDERPATH_GL20:
8984         case RENDERPATH_CGGL:
8985                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8986                 break;
8987         case RENDERPATH_D3D9:
8988         case RENDERPATH_D3D10:
8989         case RENDERPATH_D3D11:
8990                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8991                 break;
8992         }
8993         // TODO: do boxfilter scale-down in shader?
8994         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8995         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8996         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8997
8998         // we now have a bloom image in the framebuffer
8999         // copy it into the bloom image texture for later processing
9000         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);
9001         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9002 }
9003
9004 void R_Bloom_CopyHDRTexture(void)
9005 {
9006         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);
9007         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9008 }
9009
9010 void R_Bloom_MakeTexture(void)
9011 {
9012         int x, range, dir;
9013         float xoffset, yoffset, r, brighten;
9014
9015         r_refdef.stats.bloom++;
9016
9017         R_ResetViewRendering2D();
9018
9019         // we have a bloom image in the framebuffer
9020         CHECKGLERROR
9021         R_SetViewport(&r_bloomstate.viewport);
9022
9023         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9024         {
9025                 x *= 2;
9026                 r = bound(0, r_bloom_colorexponent.value / x, 1);
9027                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9028                 GL_Color(r,r,r,1);
9029                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9030                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9031                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9032                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9033
9034                 // copy the vertically blurred bloom view to a texture
9035                 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);
9036                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9037         }
9038
9039         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9040         brighten = r_bloom_brighten.value;
9041         if (r_hdr.integer)
9042                 brighten *= r_hdr_range.value;
9043         brighten = sqrt(brighten);
9044         if(range >= 1)
9045                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9046         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9047
9048         for (dir = 0;dir < 2;dir++)
9049         {
9050                 // blend on at multiple vertical offsets to achieve a vertical blur
9051                 // TODO: do offset blends using GLSL
9052                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9053                 GL_BlendFunc(GL_ONE, GL_ZERO);
9054                 for (x = -range;x <= range;x++)
9055                 {
9056                         if (!dir){xoffset = 0;yoffset = x;}
9057                         else {xoffset = x;yoffset = 0;}
9058                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
9059                         yoffset /= (float)r_bloomstate.bloomtextureheight;
9060                         // compute a texcoord array with the specified x and y offset
9061                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9062                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9063                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9064                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9065                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9066                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9067                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9068                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9069                         // this r value looks like a 'dot' particle, fading sharply to
9070                         // black at the edges
9071                         // (probably not realistic but looks good enough)
9072                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9073                         //r = brighten/(range*2+1);
9074                         r = brighten / (range * 2 + 1);
9075                         if(range >= 1)
9076                                 r *= (1 - x*x/(float)(range*range));
9077                         GL_Color(r, r, r, 1);
9078                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9079                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9080                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9081                         GL_BlendFunc(GL_ONE, GL_ONE);
9082                 }
9083
9084                 // copy the vertically blurred bloom view to a texture
9085                 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);
9086                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9087         }
9088 }
9089
9090 void R_HDR_RenderBloomTexture(void)
9091 {
9092         int oldwidth, oldheight;
9093         float oldcolorscale;
9094
9095         oldcolorscale = r_refdef.view.colorscale;
9096         oldwidth = r_refdef.view.width;
9097         oldheight = r_refdef.view.height;
9098         r_refdef.view.width = r_bloomstate.bloomwidth;
9099         r_refdef.view.height = r_bloomstate.bloomheight;
9100
9101         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
9102         // TODO: add exposure compensation features
9103         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9104
9105         r_refdef.view.showdebug = false;
9106         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9107
9108         R_ResetViewRendering3D();
9109
9110         R_ClearScreen(r_refdef.fogenabled);
9111         if (r_timereport_active)
9112                 R_TimeReport("HDRclear");
9113
9114         R_View_Update();
9115         if (r_timereport_active)
9116                 R_TimeReport("visibility");
9117
9118         // only do secondary renders with HDR if r_hdr is 2 or higher
9119         r_waterstate.numwaterplanes = 0;
9120         if (r_waterstate.enabled && r_hdr.integer >= 2)
9121                 R_RenderWaterPlanes();
9122
9123         r_refdef.view.showdebug = true;
9124         R_RenderScene();
9125         r_waterstate.numwaterplanes = 0;
9126
9127         R_ResetViewRendering2D();
9128
9129         R_Bloom_CopyHDRTexture();
9130         R_Bloom_MakeTexture();
9131
9132         // restore the view settings
9133         r_refdef.view.width = oldwidth;
9134         r_refdef.view.height = oldheight;
9135         r_refdef.view.colorscale = oldcolorscale;
9136
9137         R_ResetViewRendering3D();
9138
9139         R_ClearScreen(r_refdef.fogenabled);
9140         if (r_timereport_active)
9141                 R_TimeReport("viewclear");
9142 }
9143
9144 static void R_BlendView(void)
9145 {
9146         unsigned int permutation;
9147         float uservecs[4][4];
9148
9149         switch (vid.renderpath)
9150         {
9151         case RENDERPATH_GL20:
9152         case RENDERPATH_CGGL:
9153         case RENDERPATH_D3D9:
9154         case RENDERPATH_D3D10:
9155         case RENDERPATH_D3D11:
9156                 permutation =
9157                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9158                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9159                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9160                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9161                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9162
9163                 if (r_bloomstate.texture_screen)
9164                 {
9165                         // make sure the buffer is available
9166                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9167
9168                         R_ResetViewRendering2D();
9169
9170                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9171                         {
9172                                 // declare variables
9173                                 float speed;
9174                                 static float avgspeed;
9175
9176                                 speed = VectorLength(cl.movement_velocity);
9177
9178                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9179                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9180
9181                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9182                                 speed = bound(0, speed, 1);
9183                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9184
9185                                 // calculate values into a standard alpha
9186                                 cl.motionbluralpha = 1 - exp(-
9187                                                 (
9188                                                  (r_motionblur.value * speed / 80)
9189                                                  +
9190                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9191                                                 )
9192                                                 /
9193                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
9194                                            );
9195
9196                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9197                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9198                                 // apply the blur
9199                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9200                                 {
9201                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9202                                         GL_Color(1, 1, 1, cl.motionbluralpha);
9203                                         switch(vid.renderpath)
9204                                         {
9205                                         case RENDERPATH_GL11:
9206                                         case RENDERPATH_GL13:
9207                                         case RENDERPATH_GL20:
9208                                         case RENDERPATH_CGGL:
9209                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9210                                                 break;
9211                                         case RENDERPATH_D3D9:
9212                                         case RENDERPATH_D3D10:
9213                                         case RENDERPATH_D3D11:
9214                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9215                                                 break;
9216                                         }
9217                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9218                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9219                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9220                                 }
9221                         }
9222
9223                         // copy view into the screen texture
9224                         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);
9225                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9226                 }
9227                 else if (!r_bloomstate.texture_bloom)
9228                 {
9229                         // we may still have to do view tint...
9230                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9231                         {
9232                                 // apply a color tint to the whole view
9233                                 R_ResetViewRendering2D();
9234                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9235                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9236                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9237                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9238                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9239                         }
9240                         break; // no screen processing, no bloom, skip it
9241                 }
9242
9243                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9244                 {
9245                         // render simple bloom effect
9246                         // copy the screen and shrink it and darken it for the bloom process
9247                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9248                         // make the bloom texture
9249                         R_Bloom_MakeTexture();
9250                 }
9251
9252 #if _MSC_VER >= 1400
9253 #define sscanf sscanf_s
9254 #endif
9255                 memset(uservecs, 0, sizeof(uservecs));
9256                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9257                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9258                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9259                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9260
9261                 R_ResetViewRendering2D();
9262                 GL_Color(1, 1, 1, 1);
9263                 GL_BlendFunc(GL_ONE, GL_ZERO);
9264
9265                 switch(vid.renderpath)
9266                 {
9267                 case RENDERPATH_GL20:
9268                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9269                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9270                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9271                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9272                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9273                         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]);
9274                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9275                         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]);
9276                         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]);
9277                         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]);
9278                         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]);
9279                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9280                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9281                         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);
9282                         break;
9283                 case RENDERPATH_CGGL:
9284 #ifdef SUPPORTCG
9285                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9286                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9287                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9288                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9289                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9290                         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
9291                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9292                         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
9293                         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
9294                         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
9295                         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
9296                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9297                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9298                         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);
9299 #endif
9300                         break;
9301                 case RENDERPATH_D3D9:
9302 #ifdef SUPPORTD3D
9303                         // 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...
9304                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9305                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9306                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9307                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9308                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9309                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9310                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9311                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9312                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9313                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9314                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9315                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9316                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9317                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9318 #endif
9319                         break;
9320                 case RENDERPATH_D3D10:
9321                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9322                         break;
9323                 case RENDERPATH_D3D11:
9324                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9325                         break;
9326                 default:
9327                         break;
9328                 }
9329                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9330                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9331                 break;
9332         case RENDERPATH_GL13:
9333         case RENDERPATH_GL11:
9334                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9335                 {
9336                         // apply a color tint to the whole view
9337                         R_ResetViewRendering2D();
9338                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9339                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9340                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9341                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9342                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9343                 }
9344                 break;
9345         }
9346 }
9347
9348 matrix4x4_t r_waterscrollmatrix;
9349
9350 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9351 {
9352         if (r_refdef.fog_density)
9353         {
9354                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9355                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9356                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9357
9358                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9359                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9360                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9361                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9362
9363                 {
9364                         vec3_t fogvec;
9365                         VectorCopy(r_refdef.fogcolor, fogvec);
9366                         //   color.rgb *= ContrastBoost * SceneBrightness;
9367                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9368                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9369                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9370                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9371                 }
9372         }
9373 }
9374
9375 void R_UpdateVariables(void)
9376 {
9377         R_Textures_Frame();
9378
9379         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9380
9381         r_refdef.farclip = r_farclip_base.value;
9382         if (r_refdef.scene.worldmodel)
9383                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9384         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9385
9386         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9387                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9388         r_refdef.polygonfactor = 0;
9389         r_refdef.polygonoffset = 0;
9390         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9391         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9392
9393         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9394         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9395         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9396         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9397         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9398         if (FAKELIGHT_ENABLED)
9399         {
9400                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9401         }
9402         if (r_showsurfaces.integer)
9403         {
9404                 r_refdef.scene.rtworld = false;
9405                 r_refdef.scene.rtworldshadows = false;
9406                 r_refdef.scene.rtdlight = false;
9407                 r_refdef.scene.rtdlightshadows = false;
9408                 r_refdef.lightmapintensity = 0;
9409         }
9410
9411         if (gamemode == GAME_NEHAHRA)
9412         {
9413                 if (gl_fogenable.integer)
9414                 {
9415                         r_refdef.oldgl_fogenable = true;
9416                         r_refdef.fog_density = gl_fogdensity.value;
9417                         r_refdef.fog_red = gl_fogred.value;
9418                         r_refdef.fog_green = gl_foggreen.value;
9419                         r_refdef.fog_blue = gl_fogblue.value;
9420                         r_refdef.fog_alpha = 1;
9421                         r_refdef.fog_start = 0;
9422                         r_refdef.fog_end = gl_skyclip.value;
9423                         r_refdef.fog_height = 1<<30;
9424                         r_refdef.fog_fadedepth = 128;
9425                 }
9426                 else if (r_refdef.oldgl_fogenable)
9427                 {
9428                         r_refdef.oldgl_fogenable = false;
9429                         r_refdef.fog_density = 0;
9430                         r_refdef.fog_red = 0;
9431                         r_refdef.fog_green = 0;
9432                         r_refdef.fog_blue = 0;
9433                         r_refdef.fog_alpha = 0;
9434                         r_refdef.fog_start = 0;
9435                         r_refdef.fog_end = 0;
9436                         r_refdef.fog_height = 1<<30;
9437                         r_refdef.fog_fadedepth = 128;
9438                 }
9439         }
9440
9441         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9442         r_refdef.fog_start = max(0, r_refdef.fog_start);
9443         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9444
9445         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9446
9447         if (r_refdef.fog_density && r_drawfog.integer)
9448         {
9449                 r_refdef.fogenabled = true;
9450                 // this is the point where the fog reaches 0.9986 alpha, which we
9451                 // consider a good enough cutoff point for the texture
9452                 // (0.9986 * 256 == 255.6)
9453                 if (r_fog_exp2.integer)
9454                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9455                 else
9456                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9457                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9458                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9459                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9460                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9461                         R_BuildFogHeightTexture();
9462                 // fog color was already set
9463                 // update the fog texture
9464                 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)
9465                         R_BuildFogTexture();
9466                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9467                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9468         }
9469         else
9470                 r_refdef.fogenabled = false;
9471
9472         switch(vid.renderpath)
9473         {
9474         case RENDERPATH_GL20:
9475         case RENDERPATH_CGGL:
9476         case RENDERPATH_D3D9:
9477         case RENDERPATH_D3D10:
9478         case RENDERPATH_D3D11:
9479                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9480                 {
9481                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9482                         {
9483                                 // build GLSL gamma texture
9484 #define RAMPWIDTH 256
9485                                 unsigned short ramp[RAMPWIDTH * 3];
9486                                 unsigned char rampbgr[RAMPWIDTH][4];
9487                                 int i;
9488
9489                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9490
9491                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9492                                 for(i = 0; i < RAMPWIDTH; ++i)
9493                                 {
9494                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9495                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9496                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9497                                         rampbgr[i][3] = 0;
9498                                 }
9499                                 if (r_texture_gammaramps)
9500                                 {
9501                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9502                                 }
9503                                 else
9504                                 {
9505                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9506                                 }
9507                         }
9508                 }
9509                 else
9510                 {
9511                         // remove GLSL gamma texture
9512                 }
9513                 break;
9514         case RENDERPATH_GL13:
9515         case RENDERPATH_GL11:
9516                 break;
9517         }
9518 }
9519
9520 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9521 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9522 /*
9523 ================
9524 R_SelectScene
9525 ================
9526 */
9527 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9528         if( scenetype != r_currentscenetype ) {
9529                 // store the old scenetype
9530                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9531                 r_currentscenetype = scenetype;
9532                 // move in the new scene
9533                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9534         }
9535 }
9536
9537 /*
9538 ================
9539 R_GetScenePointer
9540 ================
9541 */
9542 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9543 {
9544         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9545         if( scenetype == r_currentscenetype ) {
9546                 return &r_refdef.scene;
9547         } else {
9548                 return &r_scenes_store[ scenetype ];
9549         }
9550 }
9551
9552 /*
9553 ================
9554 R_RenderView
9555 ================
9556 */
9557 void R_RenderView(void)
9558 {
9559         if (r_timereport_active)
9560                 R_TimeReport("start");
9561         r_textureframe++; // used only by R_GetCurrentTexture
9562         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9563
9564         if (!r_drawentities.integer)
9565                 r_refdef.scene.numentities = 0;
9566
9567         R_AnimCache_ClearCache();
9568         R_FrameData_NewFrame();
9569
9570         if (r_refdef.view.isoverlay)
9571         {
9572                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9573                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9574                 R_TimeReport("depthclear");
9575
9576                 r_refdef.view.showdebug = false;
9577
9578                 r_waterstate.enabled = false;
9579                 r_waterstate.numwaterplanes = 0;
9580
9581                 R_RenderScene();
9582
9583                 CHECKGLERROR
9584                 return;
9585         }
9586
9587         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9588                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9589
9590         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9591
9592         R_RenderView_UpdateViewVectors();
9593
9594         R_Shadow_UpdateWorldLightSelection();
9595
9596         R_Bloom_StartFrame();
9597         R_Water_StartFrame();
9598
9599         CHECKGLERROR
9600         if (r_timereport_active)
9601                 R_TimeReport("viewsetup");
9602
9603         R_ResetViewRendering3D();
9604
9605         if (r_refdef.view.clear || r_refdef.fogenabled)
9606         {
9607                 R_ClearScreen(r_refdef.fogenabled);
9608                 if (r_timereport_active)
9609                         R_TimeReport("viewclear");
9610         }
9611         r_refdef.view.clear = true;
9612
9613         // this produces a bloom texture to be used in R_BlendView() later
9614         if (r_hdr.integer && r_bloomstate.bloomwidth)
9615         {
9616                 R_HDR_RenderBloomTexture();
9617                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9618                 r_textureframe++; // used only by R_GetCurrentTexture
9619         }
9620
9621         r_refdef.view.showdebug = true;
9622
9623         R_View_Update();
9624         if (r_timereport_active)
9625                 R_TimeReport("visibility");
9626
9627         r_waterstate.numwaterplanes = 0;
9628         if (r_waterstate.enabled)
9629                 R_RenderWaterPlanes();
9630
9631         R_RenderScene();
9632         r_waterstate.numwaterplanes = 0;
9633
9634         R_BlendView();
9635         if (r_timereport_active)
9636                 R_TimeReport("blendview");
9637
9638         GL_Scissor(0, 0, vid.width, vid.height);
9639         GL_ScissorTest(false);
9640
9641         CHECKGLERROR
9642 }
9643
9644 void R_RenderWaterPlanes(void)
9645 {
9646         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9647         {
9648                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9649                 if (r_timereport_active)
9650                         R_TimeReport("waterworld");
9651         }
9652
9653         // don't let sound skip if going slow
9654         if (r_refdef.scene.extraupdate)
9655                 S_ExtraUpdate ();
9656
9657         R_DrawModelsAddWaterPlanes();
9658         if (r_timereport_active)
9659                 R_TimeReport("watermodels");
9660
9661         if (r_waterstate.numwaterplanes)
9662         {
9663                 R_Water_ProcessPlanes();
9664                 if (r_timereport_active)
9665                         R_TimeReport("waterscenes");
9666         }
9667 }
9668
9669 extern void R_DrawLightningBeams (void);
9670 extern void VM_CL_AddPolygonsToMeshQueue (void);
9671 extern void R_DrawPortals (void);
9672 extern cvar_t cl_locs_show;
9673 static void R_DrawLocs(void);
9674 static void R_DrawEntityBBoxes(void);
9675 static void R_DrawModelDecals(void);
9676 extern void R_DrawModelShadows(void);
9677 extern void R_DrawModelShadowMaps(void);
9678 extern cvar_t cl_decals_newsystem;
9679 extern qboolean r_shadow_usingdeferredprepass;
9680 void R_RenderScene(void)
9681 {
9682         qboolean shadowmapping = false;
9683
9684         if (r_timereport_active)
9685                 R_TimeReport("beginscene");
9686
9687         r_refdef.stats.renders++;
9688
9689         R_UpdateFogColor();
9690
9691         // don't let sound skip if going slow
9692         if (r_refdef.scene.extraupdate)
9693                 S_ExtraUpdate ();
9694
9695         R_MeshQueue_BeginScene();
9696
9697         R_SkyStartFrame();
9698
9699         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);
9700
9701         if (r_timereport_active)
9702                 R_TimeReport("skystartframe");
9703
9704         if (cl.csqc_vidvars.drawworld)
9705         {
9706                 // don't let sound skip if going slow
9707                 if (r_refdef.scene.extraupdate)
9708                         S_ExtraUpdate ();
9709
9710                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9711                 {
9712                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9713                         if (r_timereport_active)
9714                                 R_TimeReport("worldsky");
9715                 }
9716
9717                 if (R_DrawBrushModelsSky() && r_timereport_active)
9718                         R_TimeReport("bmodelsky");
9719
9720                 if (skyrendermasked && skyrenderlater)
9721                 {
9722                         // we have to force off the water clipping plane while rendering sky
9723                         R_SetupView(false);
9724                         R_Sky();
9725                         R_SetupView(true);
9726                         if (r_timereport_active)
9727                                 R_TimeReport("sky");
9728                 }
9729         }
9730
9731         R_AnimCache_CacheVisibleEntities();
9732         if (r_timereport_active)
9733                 R_TimeReport("animation");
9734
9735         R_Shadow_PrepareLights();
9736         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9737                 R_Shadow_PrepareModelShadows();
9738         if (r_timereport_active)
9739                 R_TimeReport("preparelights");
9740
9741         if (R_Shadow_ShadowMappingEnabled())
9742                 shadowmapping = true;
9743
9744         if (r_shadow_usingdeferredprepass)
9745                 R_Shadow_DrawPrepass();
9746
9747         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9748         {
9749                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9750                 if (r_timereport_active)
9751                         R_TimeReport("worlddepth");
9752         }
9753         if (r_depthfirst.integer >= 2)
9754         {
9755                 R_DrawModelsDepth();
9756                 if (r_timereport_active)
9757                         R_TimeReport("modeldepth");
9758         }
9759
9760         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9761         {
9762                 R_DrawModelShadowMaps();
9763                 R_ResetViewRendering3D();
9764                 // don't let sound skip if going slow
9765                 if (r_refdef.scene.extraupdate)
9766                         S_ExtraUpdate ();
9767         }
9768
9769         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9770         {
9771                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9772                 if (r_timereport_active)
9773                         R_TimeReport("world");
9774         }
9775
9776         // don't let sound skip if going slow
9777         if (r_refdef.scene.extraupdate)
9778                 S_ExtraUpdate ();
9779
9780         R_DrawModels();
9781         if (r_timereport_active)
9782                 R_TimeReport("models");
9783
9784         // don't let sound skip if going slow
9785         if (r_refdef.scene.extraupdate)
9786                 S_ExtraUpdate ();
9787
9788         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9789         {
9790                 R_DrawModelShadows();
9791                 R_ResetViewRendering3D();
9792                 // don't let sound skip if going slow
9793                 if (r_refdef.scene.extraupdate)
9794                         S_ExtraUpdate ();
9795         }
9796
9797         if (!r_shadow_usingdeferredprepass)
9798         {
9799                 R_Shadow_DrawLights();
9800                 if (r_timereport_active)
9801                         R_TimeReport("rtlights");
9802         }
9803
9804         // don't let sound skip if going slow
9805         if (r_refdef.scene.extraupdate)
9806                 S_ExtraUpdate ();
9807
9808         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9809         {
9810                 R_DrawModelShadows();
9811                 R_ResetViewRendering3D();
9812                 // don't let sound skip if going slow
9813                 if (r_refdef.scene.extraupdate)
9814                         S_ExtraUpdate ();
9815         }
9816
9817         if (cl.csqc_vidvars.drawworld)
9818         {
9819                 if (cl_decals_newsystem.integer)
9820                 {
9821                         R_DrawModelDecals();
9822                         if (r_timereport_active)
9823                                 R_TimeReport("modeldecals");
9824                 }
9825                 else
9826                 {
9827                         R_DrawDecals();
9828                         if (r_timereport_active)
9829                                 R_TimeReport("decals");
9830                 }
9831
9832                 R_DrawParticles();
9833                 if (r_timereport_active)
9834                         R_TimeReport("particles");
9835
9836                 R_DrawExplosions();
9837                 if (r_timereport_active)
9838                         R_TimeReport("explosions");
9839
9840                 R_DrawLightningBeams();
9841                 if (r_timereport_active)
9842                         R_TimeReport("lightning");
9843         }
9844
9845         VM_CL_AddPolygonsToMeshQueue();
9846
9847         if (r_refdef.view.showdebug)
9848         {
9849                 if (cl_locs_show.integer)
9850                 {
9851                         R_DrawLocs();
9852                         if (r_timereport_active)
9853                                 R_TimeReport("showlocs");
9854                 }
9855
9856                 if (r_drawportals.integer)
9857                 {
9858                         R_DrawPortals();
9859                         if (r_timereport_active)
9860                                 R_TimeReport("portals");
9861                 }
9862
9863                 if (r_showbboxes.value > 0)
9864                 {
9865                         R_DrawEntityBBoxes();
9866                         if (r_timereport_active)
9867                                 R_TimeReport("bboxes");
9868                 }
9869         }
9870
9871         R_MeshQueue_RenderTransparent();
9872         if (r_timereport_active)
9873                 R_TimeReport("drawtrans");
9874
9875         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))
9876         {
9877                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9878                 if (r_timereport_active)
9879                         R_TimeReport("worlddebug");
9880                 R_DrawModelsDebug();
9881                 if (r_timereport_active)
9882                         R_TimeReport("modeldebug");
9883         }
9884
9885         if (cl.csqc_vidvars.drawworld)
9886         {
9887                 R_Shadow_DrawCoronas();
9888                 if (r_timereport_active)
9889                         R_TimeReport("coronas");
9890         }
9891
9892 #if 0
9893         {
9894                 GL_DepthTest(false);
9895                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9896                 GL_Color(1, 1, 1, 1);
9897                 qglBegin(GL_POLYGON);
9898                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9899                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9900                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9901                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9902                 qglEnd();
9903                 qglBegin(GL_POLYGON);
9904                 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]);
9905                 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]);
9906                 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]);
9907                 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]);
9908                 qglEnd();
9909                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9910         }
9911 #endif
9912
9913         // don't let sound skip if going slow
9914         if (r_refdef.scene.extraupdate)
9915                 S_ExtraUpdate ();
9916
9917         R_ResetViewRendering2D();
9918 }
9919
9920 static const unsigned short bboxelements[36] =
9921 {
9922         5, 1, 3, 5, 3, 7,
9923         6, 2, 0, 6, 0, 4,
9924         7, 3, 2, 7, 2, 6,
9925         4, 0, 1, 4, 1, 5,
9926         4, 5, 7, 4, 7, 6,
9927         1, 0, 2, 1, 2, 3,
9928 };
9929
9930 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9931 {
9932         int i;
9933         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9934
9935         RSurf_ActiveWorldEntity();
9936
9937         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9938         GL_DepthMask(false);
9939         GL_DepthRange(0, 1);
9940         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9941         R_Mesh_ResetTextureState();
9942
9943         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9944         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9945         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9946         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9947         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9948         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9949         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9950         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9951         R_FillColors(color4f, 8, cr, cg, cb, ca);
9952         if (r_refdef.fogenabled)
9953         {
9954                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9955                 {
9956                         f1 = RSurf_FogVertex(v);
9957                         f2 = 1 - f1;
9958                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9959                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9960                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9961                 }
9962         }
9963         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9964         R_Mesh_ResetTextureState();
9965         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9966         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9967 }
9968
9969 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9970 {
9971         int i;
9972         float color[4];
9973         prvm_edict_t *edict;
9974         prvm_prog_t *prog_save = prog;
9975
9976         // this function draws bounding boxes of server entities
9977         if (!sv.active)
9978                 return;
9979
9980         GL_CullFace(GL_NONE);
9981         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9982
9983         prog = 0;
9984         SV_VM_Begin();
9985         for (i = 0;i < numsurfaces;i++)
9986         {
9987                 edict = PRVM_EDICT_NUM(surfacelist[i]);
9988                 switch ((int)edict->fields.server->solid)
9989                 {
9990                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
9991                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
9992                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
9993                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9994                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
9995                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
9996                 }
9997                 color[3] *= r_showbboxes.value;
9998                 color[3] = bound(0, color[3], 1);
9999                 GL_DepthTest(!r_showdisabledepthtest.integer);
10000                 GL_CullFace(r_refdef.view.cullface_front);
10001                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10002         }
10003         SV_VM_End();
10004         prog = prog_save;
10005 }
10006
10007 static void R_DrawEntityBBoxes(void)
10008 {
10009         int i;
10010         prvm_edict_t *edict;
10011         vec3_t center;
10012         prvm_prog_t *prog_save = prog;
10013
10014         // this function draws bounding boxes of server entities
10015         if (!sv.active)
10016                 return;
10017
10018         prog = 0;
10019         SV_VM_Begin();
10020         for (i = 0;i < prog->num_edicts;i++)
10021         {
10022                 edict = PRVM_EDICT_NUM(i);
10023                 if (edict->priv.server->free)
10024                         continue;
10025                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10026                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10027                         continue;
10028                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10029                         continue;
10030                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10031                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10032         }
10033         SV_VM_End();
10034         prog = prog_save;
10035 }
10036
10037 static const int nomodelelement3i[24] =
10038 {
10039         5, 2, 0,
10040         5, 1, 2,
10041         5, 0, 3,
10042         5, 3, 1,
10043         0, 2, 4,
10044         2, 1, 4,
10045         3, 0, 4,
10046         1, 3, 4
10047 };
10048
10049 static const unsigned short nomodelelement3s[24] =
10050 {
10051         5, 2, 0,
10052         5, 1, 2,
10053         5, 0, 3,
10054         5, 3, 1,
10055         0, 2, 4,
10056         2, 1, 4,
10057         3, 0, 4,
10058         1, 3, 4
10059 };
10060
10061 static const float nomodelvertex3f[6*3] =
10062 {
10063         -16,   0,   0,
10064          16,   0,   0,
10065           0, -16,   0,
10066           0,  16,   0,
10067           0,   0, -16,
10068           0,   0,  16
10069 };
10070
10071 static const float nomodelcolor4f[6*4] =
10072 {
10073         0.0f, 0.0f, 0.5f, 1.0f,
10074         0.0f, 0.0f, 0.5f, 1.0f,
10075         0.0f, 0.5f, 0.0f, 1.0f,
10076         0.0f, 0.5f, 0.0f, 1.0f,
10077         0.5f, 0.0f, 0.0f, 1.0f,
10078         0.5f, 0.0f, 0.0f, 1.0f
10079 };
10080
10081 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10082 {
10083         int i;
10084         float f1, f2, *c;
10085         float color4f[6*4];
10086
10087         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);
10088
10089         // this is only called once per entity so numsurfaces is always 1, and
10090         // surfacelist is always {0}, so this code does not handle batches
10091
10092         if (rsurface.ent_flags & RENDER_ADDITIVE)
10093         {
10094                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10095                 GL_DepthMask(false);
10096         }
10097         else if (rsurface.colormod[3] < 1)
10098         {
10099                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10100                 GL_DepthMask(false);
10101         }
10102         else
10103         {
10104                 GL_BlendFunc(GL_ONE, GL_ZERO);
10105                 GL_DepthMask(true);
10106         }
10107         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10108         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10109         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10110         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10111         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10112         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10113         for (i = 0, c = color4f;i < 6;i++, c += 4)
10114         {
10115                 c[0] *= rsurface.colormod[0];
10116                 c[1] *= rsurface.colormod[1];
10117                 c[2] *= rsurface.colormod[2];
10118                 c[3] *= rsurface.colormod[3];
10119         }
10120         if (r_refdef.fogenabled)
10121         {
10122                 for (i = 0, c = color4f;i < 6;i++, c += 4)
10123                 {
10124                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10125                         f2 = 1 - f1;
10126                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10127                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10128                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10129                 }
10130         }
10131         R_Mesh_ResetTextureState();
10132         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10133         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10134 }
10135
10136 void R_DrawNoModel(entity_render_t *ent)
10137 {
10138         vec3_t org;
10139         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10140         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10141                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10142         else
10143                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10144 }
10145
10146 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10147 {
10148         vec3_t right1, right2, diff, normal;
10149
10150         VectorSubtract (org2, org1, normal);
10151
10152         // calculate 'right' vector for start
10153         VectorSubtract (r_refdef.view.origin, org1, diff);
10154         CrossProduct (normal, diff, right1);
10155         VectorNormalize (right1);
10156
10157         // calculate 'right' vector for end
10158         VectorSubtract (r_refdef.view.origin, org2, diff);
10159         CrossProduct (normal, diff, right2);
10160         VectorNormalize (right2);
10161
10162         vert[ 0] = org1[0] + width * right1[0];
10163         vert[ 1] = org1[1] + width * right1[1];
10164         vert[ 2] = org1[2] + width * right1[2];
10165         vert[ 3] = org1[0] - width * right1[0];
10166         vert[ 4] = org1[1] - width * right1[1];
10167         vert[ 5] = org1[2] - width * right1[2];
10168         vert[ 6] = org2[0] - width * right2[0];
10169         vert[ 7] = org2[1] - width * right2[1];
10170         vert[ 8] = org2[2] - width * right2[2];
10171         vert[ 9] = org2[0] + width * right2[0];
10172         vert[10] = org2[1] + width * right2[1];
10173         vert[11] = org2[2] + width * right2[2];
10174 }
10175
10176 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)
10177 {
10178         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10179         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10180         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10181         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10182         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10183         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10184         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10185         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10186         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10187         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10188         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10189         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10190 }
10191
10192 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10193 {
10194         int i;
10195         float *vertex3f;
10196         float v[3];
10197         VectorSet(v, x, y, z);
10198         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10199                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10200                         break;
10201         if (i == mesh->numvertices)
10202         {
10203                 if (mesh->numvertices < mesh->maxvertices)
10204                 {
10205                         VectorCopy(v, vertex3f);
10206                         mesh->numvertices++;
10207                 }
10208                 return mesh->numvertices;
10209         }
10210         else
10211                 return i;
10212 }
10213
10214 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10215 {
10216         int i;
10217         int *e, element[3];
10218         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10219         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10220         e = mesh->element3i + mesh->numtriangles * 3;
10221         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10222         {
10223                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10224                 if (mesh->numtriangles < mesh->maxtriangles)
10225                 {
10226                         *e++ = element[0];
10227                         *e++ = element[1];
10228                         *e++ = element[2];
10229                         mesh->numtriangles++;
10230                 }
10231                 element[1] = element[2];
10232         }
10233 }
10234
10235 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10236 {
10237         int i;
10238         int *e, element[3];
10239         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10240         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10241         e = mesh->element3i + mesh->numtriangles * 3;
10242         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10243         {
10244                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10245                 if (mesh->numtriangles < mesh->maxtriangles)
10246                 {
10247                         *e++ = element[0];
10248                         *e++ = element[1];
10249                         *e++ = element[2];
10250                         mesh->numtriangles++;
10251                 }
10252                 element[1] = element[2];
10253         }
10254 }
10255
10256 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10257 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10258 {
10259         int planenum, planenum2;
10260         int w;
10261         int tempnumpoints;
10262         mplane_t *plane, *plane2;
10263         double maxdist;
10264         double temppoints[2][256*3];
10265         // figure out how large a bounding box we need to properly compute this brush
10266         maxdist = 0;
10267         for (w = 0;w < numplanes;w++)
10268                 maxdist = max(maxdist, fabs(planes[w].dist));
10269         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10270         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10271         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10272         {
10273                 w = 0;
10274                 tempnumpoints = 4;
10275                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10276                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10277                 {
10278                         if (planenum2 == planenum)
10279                                 continue;
10280                         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);
10281                         w = !w;
10282                 }
10283                 if (tempnumpoints < 3)
10284                         continue;
10285                 // generate elements forming a triangle fan for this polygon
10286                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10287         }
10288 }
10289
10290 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)
10291 {
10292         texturelayer_t *layer;
10293         layer = t->currentlayers + t->currentnumlayers++;
10294         layer->type = type;
10295         layer->depthmask = depthmask;
10296         layer->blendfunc1 = blendfunc1;
10297         layer->blendfunc2 = blendfunc2;
10298         layer->texture = texture;
10299         layer->texmatrix = *matrix;
10300         layer->color[0] = r;
10301         layer->color[1] = g;
10302         layer->color[2] = b;
10303         layer->color[3] = a;
10304 }
10305
10306 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10307 {
10308         if(parms[0] == 0 && parms[1] == 0)
10309                 return false;
10310         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10311                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10312                         return false;
10313         return true;
10314 }
10315
10316 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10317 {
10318         double index, f;
10319         index = parms[2] + r_refdef.scene.time * parms[3];
10320         index -= floor(index);
10321         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10322         {
10323         default:
10324         case Q3WAVEFUNC_NONE:
10325         case Q3WAVEFUNC_NOISE:
10326         case Q3WAVEFUNC_COUNT:
10327                 f = 0;
10328                 break;
10329         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10330         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10331         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10332         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10333         case Q3WAVEFUNC_TRIANGLE:
10334                 index *= 4;
10335                 f = index - floor(index);
10336                 if (index < 1)
10337                         f = f;
10338                 else if (index < 2)
10339                         f = 1 - f;
10340                 else if (index < 3)
10341                         f = -f;
10342                 else
10343                         f = -(1 - f);
10344                 break;
10345         }
10346         f = parms[0] + parms[1] * f;
10347         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10348                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10349         return (float) f;
10350 }
10351
10352 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10353 {
10354         int w, h, idx;
10355         float f;
10356         float tcmat[12];
10357         matrix4x4_t matrix, temp;
10358         switch(tcmod->tcmod)
10359         {
10360                 case Q3TCMOD_COUNT:
10361                 case Q3TCMOD_NONE:
10362                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10363                                 matrix = r_waterscrollmatrix;
10364                         else
10365                                 matrix = identitymatrix;
10366                         break;
10367                 case Q3TCMOD_ENTITYTRANSLATE:
10368                         // this is used in Q3 to allow the gamecode to control texcoord
10369                         // scrolling on the entity, which is not supported in darkplaces yet.
10370                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10371                         break;
10372                 case Q3TCMOD_ROTATE:
10373                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10374                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10375                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10376                         break;
10377                 case Q3TCMOD_SCALE:
10378                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10379                         break;
10380                 case Q3TCMOD_SCROLL:
10381                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10382                         break;
10383                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10384                         w = (int) tcmod->parms[0];
10385                         h = (int) tcmod->parms[1];
10386                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10387                         f = f - floor(f);
10388                         idx = (int) floor(f * w * h);
10389                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10390                         break;
10391                 case Q3TCMOD_STRETCH:
10392                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10393                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10394                         break;
10395                 case Q3TCMOD_TRANSFORM:
10396                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10397                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10398                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10399                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10400                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10401                         break;
10402                 case Q3TCMOD_TURBULENT:
10403                         // this is handled in the RSurf_PrepareVertices function
10404                         matrix = identitymatrix;
10405                         break;
10406         }
10407         temp = *texmatrix;
10408         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10409 }
10410
10411 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10412 {
10413         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10414         char name[MAX_QPATH];
10415         skinframe_t *skinframe;
10416         unsigned char pixels[296*194];
10417         strlcpy(cache->name, skinname, sizeof(cache->name));
10418         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10419         if (developer_loading.integer)
10420                 Con_Printf("loading %s\n", name);
10421         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10422         if (!skinframe || !skinframe->base)
10423         {
10424                 unsigned char *f;
10425                 fs_offset_t filesize;
10426                 skinframe = NULL;
10427                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10428                 if (f)
10429                 {
10430                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10431                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10432                         Mem_Free(f);
10433                 }
10434         }
10435         cache->skinframe = skinframe;
10436 }
10437
10438 texture_t *R_GetCurrentTexture(texture_t *t)
10439 {
10440         int i;
10441         const entity_render_t *ent = rsurface.entity;
10442         dp_model_t *model = ent->model;
10443         q3shaderinfo_layer_tcmod_t *tcmod;
10444
10445         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10446                 return t->currentframe;
10447         t->update_lastrenderframe = r_textureframe;
10448         t->update_lastrenderentity = (void *)ent;
10449
10450         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10451                 t->camera_entity = ent->entitynumber;
10452         else
10453                 t->camera_entity = 0;
10454
10455         // switch to an alternate material if this is a q1bsp animated material
10456         {
10457                 texture_t *texture = t;
10458                 int s = rsurface.ent_skinnum;
10459                 if ((unsigned int)s >= (unsigned int)model->numskins)
10460                         s = 0;
10461                 if (model->skinscenes)
10462                 {
10463                         if (model->skinscenes[s].framecount > 1)
10464                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10465                         else
10466                                 s = model->skinscenes[s].firstframe;
10467                 }
10468                 if (s > 0)
10469                         t = t + s * model->num_surfaces;
10470                 if (t->animated)
10471                 {
10472                         // use an alternate animation if the entity's frame is not 0,
10473                         // and only if the texture has an alternate animation
10474                         if (rsurface.ent_alttextures && t->anim_total[1])
10475                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10476                         else
10477                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10478                 }
10479                 texture->currentframe = t;
10480         }
10481
10482         // update currentskinframe to be a qw skin or animation frame
10483         if (rsurface.ent_qwskin >= 0)
10484         {
10485                 i = rsurface.ent_qwskin;
10486                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10487                 {
10488                         r_qwskincache_size = cl.maxclients;
10489                         if (r_qwskincache)
10490                                 Mem_Free(r_qwskincache);
10491                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10492                 }
10493                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10494                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10495                 t->currentskinframe = r_qwskincache[i].skinframe;
10496                 if (t->currentskinframe == NULL)
10497                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10498         }
10499         else if (t->numskinframes >= 2)
10500                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10501         if (t->backgroundnumskinframes >= 2)
10502                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10503
10504         t->currentmaterialflags = t->basematerialflags;
10505         t->currentalpha = rsurface.colormod[3];
10506         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10507                 t->currentalpha *= r_wateralpha.value;
10508         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10509                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10510         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10511                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10512         if (!(rsurface.ent_flags & RENDER_LIGHT))
10513                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10514         else if (FAKELIGHT_ENABLED)
10515         {
10516                         // no modellight if using fakelight for the map
10517         }
10518         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10519         {
10520                 // pick a model lighting mode
10521                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10522                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10523                 else
10524                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10525         }
10526         if (rsurface.ent_flags & RENDER_ADDITIVE)
10527                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10528         else if (t->currentalpha < 1)
10529                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10530         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10531                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10532         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10533                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10534         if (t->backgroundnumskinframes)
10535                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10536         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10537         {
10538                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10539                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10540         }
10541         else
10542                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10543         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10544                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10545
10546         // there is no tcmod
10547         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10548         {
10549                 t->currenttexmatrix = r_waterscrollmatrix;
10550                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10551         }
10552         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10553         {
10554                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10555                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10556         }
10557
10558         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10559                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10560         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10561                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10562
10563         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10564         if (t->currentskinframe->qpixels)
10565                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10566         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10567         if (!t->basetexture)
10568                 t->basetexture = r_texture_notexture;
10569         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10570         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10571         t->nmaptexture = t->currentskinframe->nmap;
10572         if (!t->nmaptexture)
10573                 t->nmaptexture = r_texture_blanknormalmap;
10574         t->glosstexture = r_texture_black;
10575         t->glowtexture = t->currentskinframe->glow;
10576         t->fogtexture = t->currentskinframe->fog;
10577         t->reflectmasktexture = t->currentskinframe->reflect;
10578         if (t->backgroundnumskinframes)
10579         {
10580                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10581                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10582                 t->backgroundglosstexture = r_texture_black;
10583                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10584                 if (!t->backgroundnmaptexture)
10585                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10586         }
10587         else
10588         {
10589                 t->backgroundbasetexture = r_texture_white;
10590                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10591                 t->backgroundglosstexture = r_texture_black;
10592                 t->backgroundglowtexture = NULL;
10593         }
10594         t->specularpower = r_shadow_glossexponent.value;
10595         // TODO: store reference values for these in the texture?
10596         t->specularscale = 0;
10597         if (r_shadow_gloss.integer > 0)
10598         {
10599                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10600                 {
10601                         if (r_shadow_glossintensity.value > 0)
10602                         {
10603                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10604                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10605                                 t->specularscale = r_shadow_glossintensity.value;
10606                         }
10607                 }
10608                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10609                 {
10610                         t->glosstexture = r_texture_white;
10611                         t->backgroundglosstexture = r_texture_white;
10612                         t->specularscale = r_shadow_gloss2intensity.value;
10613                         t->specularpower = r_shadow_gloss2exponent.value;
10614                 }
10615         }
10616         t->specularscale *= t->specularscalemod;
10617         t->specularpower *= t->specularpowermod;
10618
10619         // lightmaps mode looks bad with dlights using actual texturing, so turn
10620         // off the colormap and glossmap, but leave the normalmap on as it still
10621         // accurately represents the shading involved
10622         if (gl_lightmaps.integer)
10623         {
10624                 t->basetexture = r_texture_grey128;
10625                 t->pantstexture = r_texture_black;
10626                 t->shirttexture = r_texture_black;
10627                 t->nmaptexture = r_texture_blanknormalmap;
10628                 t->glosstexture = r_texture_black;
10629                 t->glowtexture = NULL;
10630                 t->fogtexture = NULL;
10631                 t->reflectmasktexture = NULL;
10632                 t->backgroundbasetexture = NULL;
10633                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10634                 t->backgroundglosstexture = r_texture_black;
10635                 t->backgroundglowtexture = NULL;
10636                 t->specularscale = 0;
10637                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10638         }
10639
10640         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10641         VectorClear(t->dlightcolor);
10642         t->currentnumlayers = 0;
10643         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10644         {
10645                 int blendfunc1, blendfunc2;
10646                 qboolean depthmask;
10647                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10648                 {
10649                         blendfunc1 = GL_SRC_ALPHA;
10650                         blendfunc2 = GL_ONE;
10651                 }
10652                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10653                 {
10654                         blendfunc1 = GL_SRC_ALPHA;
10655                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10656                 }
10657                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10658                 {
10659                         blendfunc1 = t->customblendfunc[0];
10660                         blendfunc2 = t->customblendfunc[1];
10661                 }
10662                 else
10663                 {
10664                         blendfunc1 = GL_ONE;
10665                         blendfunc2 = GL_ZERO;
10666                 }
10667                 // don't colormod evilblend textures
10668                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10669                         VectorSet(t->lightmapcolor, 1, 1, 1);
10670                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10671                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10672                 {
10673                         // fullbright is not affected by r_refdef.lightmapintensity
10674                         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]);
10675                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10676                                 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]);
10677                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10678                                 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]);
10679                 }
10680                 else
10681                 {
10682                         vec3_t ambientcolor;
10683                         float colorscale;
10684                         // set the color tint used for lights affecting this surface
10685                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10686                         colorscale = 2;
10687                         // q3bsp has no lightmap updates, so the lightstylevalue that
10688                         // would normally be baked into the lightmap must be
10689                         // applied to the color
10690                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10691                         if (model->type == mod_brushq3)
10692                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10693                         colorscale *= r_refdef.lightmapintensity;
10694                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10695                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10696                         // basic lit geometry
10697                         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]);
10698                         // add pants/shirt if needed
10699                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10700                                 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]);
10701                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10702                                 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]);
10703                         // now add ambient passes if needed
10704                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10705                         {
10706                                 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]);
10707                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10708                                         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]);
10709                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10710                                         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]);
10711                         }
10712                 }
10713                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10714                         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]);
10715                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10716                 {
10717                         // if this is opaque use alpha blend which will darken the earlier
10718                         // passes cheaply.
10719                         //
10720                         // if this is an alpha blended material, all the earlier passes
10721                         // were darkened by fog already, so we only need to add the fog
10722                         // color ontop through the fog mask texture
10723                         //
10724                         // if this is an additive blended material, all the earlier passes
10725                         // were darkened by fog already, and we should not add fog color
10726                         // (because the background was not darkened, there is no fog color
10727                         // that was lost behind it).
10728                         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]);
10729                 }
10730         }
10731
10732         return t->currentframe;
10733 }
10734
10735 rsurfacestate_t rsurface;
10736
10737 void R_Mesh_ResizeArrays(int newvertices)
10738 {
10739         unsigned char *base;
10740         size_t size;
10741         if (rsurface.array_size >= newvertices)
10742                 return;
10743         if (rsurface.array_base)
10744                 Mem_Free(rsurface.array_base);
10745         rsurface.array_size = (newvertices + 1023) & ~1023;
10746         size = 0;
10747         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10748         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10749         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10750         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10751         size += rsurface.array_size * sizeof(float[3]);
10752         size += rsurface.array_size * sizeof(float[3]);
10753         size += rsurface.array_size * sizeof(float[3]);
10754         size += rsurface.array_size * sizeof(float[3]);
10755         size += rsurface.array_size * sizeof(float[3]);
10756         size += rsurface.array_size * sizeof(float[3]);
10757         size += rsurface.array_size * sizeof(float[3]);
10758         size += rsurface.array_size * sizeof(float[3]);
10759         size += rsurface.array_size * sizeof(float[4]);
10760         size += rsurface.array_size * sizeof(float[2]);
10761         size += rsurface.array_size * sizeof(float[2]);
10762         size += rsurface.array_size * sizeof(float[4]);
10763         size += rsurface.array_size * sizeof(int[3]);
10764         size += rsurface.array_size * sizeof(unsigned short[3]);
10765         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10766         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10767         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10768         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10769         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10770         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10771         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10772         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10773         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10774         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10775         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10776         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10777         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10778         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10779         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10780         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10781         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10782         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
10783         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10784 }
10785
10786 void RSurf_ActiveWorldEntity(void)
10787 {
10788         dp_model_t *model = r_refdef.scene.worldmodel;
10789         //if (rsurface.entity == r_refdef.scene.worldentity)
10790         //      return;
10791         rsurface.entity = r_refdef.scene.worldentity;
10792         rsurface.skeleton = NULL;
10793         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10794         rsurface.ent_skinnum = 0;
10795         rsurface.ent_qwskin = -1;
10796         rsurface.ent_shadertime = 0;
10797         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10798         if (rsurface.array_size < model->surfmesh.num_vertices)
10799                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10800         rsurface.matrix = identitymatrix;
10801         rsurface.inversematrix = identitymatrix;
10802         rsurface.matrixscale = 1;
10803         rsurface.inversematrixscale = 1;
10804         R_EntityMatrix(&identitymatrix);
10805         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10806         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10807         rsurface.fograngerecip = r_refdef.fograngerecip;
10808         rsurface.fogheightfade = r_refdef.fogheightfade;
10809         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10810         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10811         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10812         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10813         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10814         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10815         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10816         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10817         rsurface.colormod[3] = 1;
10818         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);
10819         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10820         rsurface.frameblend[0].lerp = 1;
10821         rsurface.ent_alttextures = false;
10822         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10823         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10824         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10825         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10826         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10827         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10828         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10829         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10830         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10831         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10832         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10833         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10834         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10835         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10836         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10837         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10838         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10839         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10840         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10841         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10842         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10843         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10844         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10845         rsurface.modelelement3i = model->surfmesh.data_element3i;
10846         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10847         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10848         rsurface.modelelement3s = model->surfmesh.data_element3s;
10849         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10850         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10851         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10852         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10853         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10854         rsurface.modelsurfaces = model->data_surfaces;
10855         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10856         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10857         rsurface.modelvertexposition = model->surfmesh.vertexposition;
10858         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10859         rsurface.modelgeneratedvertex = false;
10860         rsurface.batchgeneratedvertex = false;
10861         rsurface.batchfirstvertex = 0;
10862         rsurface.batchnumvertices = 0;
10863         rsurface.batchfirsttriangle = 0;
10864         rsurface.batchnumtriangles = 0;
10865         rsurface.batchvertex3f  = NULL;
10866         rsurface.batchvertex3f_vertexbuffer = NULL;
10867         rsurface.batchvertex3f_bufferoffset = 0;
10868         rsurface.batchsvector3f = NULL;
10869         rsurface.batchsvector3f_vertexbuffer = NULL;
10870         rsurface.batchsvector3f_bufferoffset = 0;
10871         rsurface.batchtvector3f = NULL;
10872         rsurface.batchtvector3f_vertexbuffer = NULL;
10873         rsurface.batchtvector3f_bufferoffset = 0;
10874         rsurface.batchnormal3f  = NULL;
10875         rsurface.batchnormal3f_vertexbuffer = NULL;
10876         rsurface.batchnormal3f_bufferoffset = 0;
10877         rsurface.batchlightmapcolor4f = NULL;
10878         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10879         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10880         rsurface.batchtexcoordtexture2f = NULL;
10881         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10882         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10883         rsurface.batchtexcoordlightmap2f = NULL;
10884         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10885         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10886         rsurface.batchvertexmesh = NULL;
10887         rsurface.batchvertexmeshbuffer = NULL;
10888         rsurface.batchvertexposition = NULL;
10889         rsurface.batchvertexpositionbuffer = NULL;
10890         rsurface.batchelement3i = NULL;
10891         rsurface.batchelement3i_indexbuffer = NULL;
10892         rsurface.batchelement3i_bufferoffset = 0;
10893         rsurface.batchelement3s = NULL;
10894         rsurface.batchelement3s_indexbuffer = NULL;
10895         rsurface.batchelement3s_bufferoffset = 0;
10896         rsurface.passcolor4f = NULL;
10897         rsurface.passcolor4f_vertexbuffer = NULL;
10898         rsurface.passcolor4f_bufferoffset = 0;
10899 }
10900
10901 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10902 {
10903         dp_model_t *model = ent->model;
10904         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10905         //      return;
10906         rsurface.entity = (entity_render_t *)ent;
10907         rsurface.skeleton = ent->skeleton;
10908         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10909         rsurface.ent_skinnum = ent->skinnum;
10910         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;
10911         rsurface.ent_shadertime = ent->shadertime;
10912         rsurface.ent_flags = ent->flags;
10913         if (rsurface.array_size < model->surfmesh.num_vertices)
10914                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10915         rsurface.matrix = ent->matrix;
10916         rsurface.inversematrix = ent->inversematrix;
10917         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10918         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10919         R_EntityMatrix(&rsurface.matrix);
10920         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10921         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10922         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10923         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10924         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10925         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10926         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10927         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10928         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10929         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10930         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10931         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10932         rsurface.colormod[3] = ent->alpha;
10933         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10934         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10935         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10936         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10937         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10938         if (ent->model->brush.submodel && !prepass)
10939         {
10940                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10941                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10942         }
10943         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10944         {
10945                 if (ent->animcache_vertex3f && !r_framedata_failed)
10946                 {
10947                         rsurface.modelvertex3f = ent->animcache_vertex3f;
10948                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10949                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10950                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10951                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10952                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10953                         rsurface.modelvertexposition = ent->animcache_vertexposition;
10954                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
10955                 }
10956                 else if (wanttangents)
10957                 {
10958                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10959                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10960                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10961                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10962                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
10963                         rsurface.modelvertexmesh = NULL;
10964                         rsurface.modelvertexmeshbuffer = NULL;
10965                         rsurface.modelvertexposition = NULL;
10966                         rsurface.modelvertexpositionbuffer = NULL;
10967                 }
10968                 else if (wantnormals)
10969                 {
10970                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10971                         rsurface.modelsvector3f = NULL;
10972                         rsurface.modeltvector3f = NULL;
10973                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10974                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
10975                         rsurface.modelvertexmesh = NULL;
10976                         rsurface.modelvertexmeshbuffer = NULL;
10977                         rsurface.modelvertexposition = NULL;
10978                         rsurface.modelvertexpositionbuffer = NULL;
10979                 }
10980                 else
10981                 {
10982                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10983                         rsurface.modelsvector3f = NULL;
10984                         rsurface.modeltvector3f = NULL;
10985                         rsurface.modelnormal3f = NULL;
10986                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
10987                         rsurface.modelvertexmesh = NULL;
10988                         rsurface.modelvertexmeshbuffer = NULL;
10989                         rsurface.modelvertexposition = NULL;
10990                         rsurface.modelvertexpositionbuffer = NULL;
10991                 }
10992                 rsurface.modelvertex3f_vertexbuffer = 0;
10993                 rsurface.modelvertex3f_bufferoffset = 0;
10994                 rsurface.modelsvector3f_vertexbuffer = 0;
10995                 rsurface.modelsvector3f_bufferoffset = 0;
10996                 rsurface.modeltvector3f_vertexbuffer = 0;
10997                 rsurface.modeltvector3f_bufferoffset = 0;
10998                 rsurface.modelnormal3f_vertexbuffer = 0;
10999                 rsurface.modelnormal3f_bufferoffset = 0;
11000                 rsurface.modelgeneratedvertex = true;
11001         }
11002         else
11003         {
11004                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
11005                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11006                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11007                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11008                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11009                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11010                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11011                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11012                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11013                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
11014                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11015                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11016                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11017                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11018                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
11019                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
11020                 rsurface.modelgeneratedvertex = false;
11021         }
11022         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11023         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11024         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11025         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11026         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11027         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11028         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11029         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11030         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11031         rsurface.modelelement3i = model->surfmesh.data_element3i;
11032         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11033         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11034         rsurface.modelelement3s = model->surfmesh.data_element3s;
11035         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11036         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11037         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11038         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11039         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11040         rsurface.modelsurfaces = model->data_surfaces;
11041         rsurface.batchgeneratedvertex = false;
11042         rsurface.batchfirstvertex = 0;
11043         rsurface.batchnumvertices = 0;
11044         rsurface.batchfirsttriangle = 0;
11045         rsurface.batchnumtriangles = 0;
11046         rsurface.batchvertex3f  = NULL;
11047         rsurface.batchvertex3f_vertexbuffer = NULL;
11048         rsurface.batchvertex3f_bufferoffset = 0;
11049         rsurface.batchsvector3f = NULL;
11050         rsurface.batchsvector3f_vertexbuffer = NULL;
11051         rsurface.batchsvector3f_bufferoffset = 0;
11052         rsurface.batchtvector3f = NULL;
11053         rsurface.batchtvector3f_vertexbuffer = NULL;
11054         rsurface.batchtvector3f_bufferoffset = 0;
11055         rsurface.batchnormal3f  = NULL;
11056         rsurface.batchnormal3f_vertexbuffer = NULL;
11057         rsurface.batchnormal3f_bufferoffset = 0;
11058         rsurface.batchlightmapcolor4f = NULL;
11059         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11060         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11061         rsurface.batchtexcoordtexture2f = NULL;
11062         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11063         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11064         rsurface.batchtexcoordlightmap2f = NULL;
11065         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11066         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11067         rsurface.batchvertexmesh = NULL;
11068         rsurface.batchvertexmeshbuffer = NULL;
11069         rsurface.batchvertexposition = NULL;
11070         rsurface.batchvertexpositionbuffer = NULL;
11071         rsurface.batchelement3i = NULL;
11072         rsurface.batchelement3i_indexbuffer = NULL;
11073         rsurface.batchelement3i_bufferoffset = 0;
11074         rsurface.batchelement3s = NULL;
11075         rsurface.batchelement3s_indexbuffer = NULL;
11076         rsurface.batchelement3s_bufferoffset = 0;
11077         rsurface.passcolor4f = NULL;
11078         rsurface.passcolor4f_vertexbuffer = NULL;
11079         rsurface.passcolor4f_bufferoffset = 0;
11080 }
11081
11082 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)
11083 {
11084         int i;
11085
11086         rsurface.entity = r_refdef.scene.worldentity;
11087         rsurface.skeleton = NULL;
11088         rsurface.ent_skinnum = 0;
11089         rsurface.ent_qwskin = -1;
11090         rsurface.ent_shadertime = shadertime;
11091         rsurface.ent_flags = entflags;
11092         rsurface.modelnumvertices = numvertices;
11093         rsurface.modelnumtriangles = numtriangles;
11094         if (rsurface.array_size < rsurface.modelnumvertices)
11095                 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
11096         rsurface.matrix = *matrix;
11097         rsurface.inversematrix = *inversematrix;
11098         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11099         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11100         R_EntityMatrix(&rsurface.matrix);
11101         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11102         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11103         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11104         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11105         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11106         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11107         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11108         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11109         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11110         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11111         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11112         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11113         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);
11114         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11115         rsurface.frameblend[0].lerp = 1;
11116         rsurface.ent_alttextures = false;
11117         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11118         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11119         if (wanttangents)
11120         {
11121                 rsurface.modelvertex3f = vertex3f;
11122                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
11123                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
11124                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11125         }
11126         else if (wantnormals)
11127         {
11128                 rsurface.modelvertex3f = vertex3f;
11129                 rsurface.modelsvector3f = NULL;
11130                 rsurface.modeltvector3f = NULL;
11131                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11132         }
11133         else
11134         {
11135                 rsurface.modelvertex3f = vertex3f;
11136                 rsurface.modelsvector3f = NULL;
11137                 rsurface.modeltvector3f = NULL;
11138                 rsurface.modelnormal3f = NULL;
11139         }
11140         rsurface.modelvertexmesh = NULL;
11141         rsurface.modelvertexmeshbuffer = NULL;
11142         rsurface.modelvertexposition = NULL;
11143         rsurface.modelvertexpositionbuffer = NULL;
11144         rsurface.modelvertex3f_vertexbuffer = 0;
11145         rsurface.modelvertex3f_bufferoffset = 0;
11146         rsurface.modelsvector3f_vertexbuffer = 0;
11147         rsurface.modelsvector3f_bufferoffset = 0;
11148         rsurface.modeltvector3f_vertexbuffer = 0;
11149         rsurface.modeltvector3f_bufferoffset = 0;
11150         rsurface.modelnormal3f_vertexbuffer = 0;
11151         rsurface.modelnormal3f_bufferoffset = 0;
11152         rsurface.modelgeneratedvertex = true;
11153         rsurface.modellightmapcolor4f  = color4f;
11154         rsurface.modellightmapcolor4f_vertexbuffer = 0;
11155         rsurface.modellightmapcolor4f_bufferoffset = 0;
11156         rsurface.modeltexcoordtexture2f  = texcoord2f;
11157         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11158         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11159         rsurface.modeltexcoordlightmap2f  = NULL;
11160         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11161         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11162         rsurface.modelelement3i = element3i;
11163         rsurface.modelelement3i_indexbuffer = NULL;
11164         rsurface.modelelement3i_bufferoffset = 0;
11165         rsurface.modelelement3s = element3s;
11166         rsurface.modelelement3s_indexbuffer = NULL;
11167         rsurface.modelelement3s_bufferoffset = 0;
11168         rsurface.modellightmapoffsets = NULL;
11169         rsurface.modelsurfaces = NULL;
11170         rsurface.batchgeneratedvertex = false;
11171         rsurface.batchfirstvertex = 0;
11172         rsurface.batchnumvertices = 0;
11173         rsurface.batchfirsttriangle = 0;
11174         rsurface.batchnumtriangles = 0;
11175         rsurface.batchvertex3f  = NULL;
11176         rsurface.batchvertex3f_vertexbuffer = NULL;
11177         rsurface.batchvertex3f_bufferoffset = 0;
11178         rsurface.batchsvector3f = NULL;
11179         rsurface.batchsvector3f_vertexbuffer = NULL;
11180         rsurface.batchsvector3f_bufferoffset = 0;
11181         rsurface.batchtvector3f = NULL;
11182         rsurface.batchtvector3f_vertexbuffer = NULL;
11183         rsurface.batchtvector3f_bufferoffset = 0;
11184         rsurface.batchnormal3f  = NULL;
11185         rsurface.batchnormal3f_vertexbuffer = NULL;
11186         rsurface.batchnormal3f_bufferoffset = 0;
11187         rsurface.batchlightmapcolor4f = NULL;
11188         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11189         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11190         rsurface.batchtexcoordtexture2f = NULL;
11191         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11192         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11193         rsurface.batchtexcoordlightmap2f = NULL;
11194         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11195         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11196         rsurface.batchvertexmesh = NULL;
11197         rsurface.batchvertexmeshbuffer = NULL;
11198         rsurface.batchvertexposition = NULL;
11199         rsurface.batchvertexpositionbuffer = NULL;
11200         rsurface.batchelement3i = NULL;
11201         rsurface.batchelement3i_indexbuffer = NULL;
11202         rsurface.batchelement3i_bufferoffset = 0;
11203         rsurface.batchelement3s = NULL;
11204         rsurface.batchelement3s_indexbuffer = NULL;
11205         rsurface.batchelement3s_bufferoffset = 0;
11206         rsurface.passcolor4f = NULL;
11207         rsurface.passcolor4f_vertexbuffer = NULL;
11208         rsurface.passcolor4f_bufferoffset = 0;
11209
11210         if (rsurface.modelnumvertices && rsurface.modelelement3i)
11211         {
11212                 if ((wantnormals || wanttangents) && !normal3f)
11213                 {
11214                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11215                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11216                 }
11217                 if (wanttangents && !svector3f)
11218                 {
11219                         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);
11220                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11221                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11222                 }
11223         }
11224
11225         // now convert arrays into vertexmesh structs
11226         for (i = 0;i < numvertices;i++)
11227         {
11228                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
11229                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
11230                 if (rsurface.modelsvector3f)
11231                         VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
11232                 if (rsurface.modeltvector3f)
11233                         VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
11234                 if (rsurface.modelnormal3f)
11235                         VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
11236                 if (rsurface.modellightmapcolor4f)
11237                         Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
11238                 if (rsurface.modeltexcoordtexture2f)
11239                         Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
11240                 if (rsurface.modeltexcoordlightmap2f)
11241                         Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
11242         }
11243 }
11244
11245 float RSurf_FogPoint(const float *v)
11246 {
11247         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11248         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11249         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11250         float FogHeightFade = r_refdef.fogheightfade;
11251         float fogfrac;
11252         unsigned int fogmasktableindex;
11253         if (r_refdef.fogplaneviewabove)
11254                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11255         else
11256                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11257         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11258         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11259 }
11260
11261 float RSurf_FogVertex(const float *v)
11262 {
11263         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11264         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11265         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11266         float FogHeightFade = rsurface.fogheightfade;
11267         float fogfrac;
11268         unsigned int fogmasktableindex;
11269         if (r_refdef.fogplaneviewabove)
11270                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11271         else
11272                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11273         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11274         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11275 }
11276
11277 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11278 {
11279         int i;
11280         for (i = 0;i < numelements;i++)
11281                 outelement3i[i] = inelement3i[i] + adjust;
11282 }
11283
11284 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11285 extern cvar_t gl_vbo;
11286 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11287 {
11288         int deformindex;
11289         int firsttriangle;
11290         int numtriangles;
11291         int firstvertex;
11292         int endvertex;
11293         int numvertices;
11294         int surfacefirsttriangle;
11295         int surfacenumtriangles;
11296         int surfacefirstvertex;
11297         int surfaceendvertex;
11298         int surfacenumvertices;
11299         int needsupdate;
11300         int i, j;
11301         qboolean gaps;
11302         qboolean dynamicvertex;
11303         float amplitude;
11304         float animpos;
11305         float scale;
11306         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11307         float waveparms[4];
11308         q3shaderinfo_deform_t *deform;
11309         const msurface_t *surface, *firstsurface;
11310         r_vertexposition_t *vertexposition;
11311         r_vertexmesh_t *vertexmesh;
11312         if (!texturenumsurfaces)
11313                 return;
11314         // find vertex range of this surface batch
11315         gaps = false;
11316         firstsurface = texturesurfacelist[0];
11317         firsttriangle = firstsurface->num_firsttriangle;
11318         numtriangles = 0;
11319         firstvertex = endvertex = firstsurface->num_firstvertex;
11320         for (i = 0;i < texturenumsurfaces;i++)
11321         {
11322                 surface = texturesurfacelist[i];
11323                 if (surface != firstsurface + i)
11324                         gaps = true;
11325                 surfacefirstvertex = surface->num_firstvertex;
11326                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11327                 surfacenumtriangles = surface->num_triangles;
11328                 if (firstvertex > surfacefirstvertex)
11329                         firstvertex = surfacefirstvertex;
11330                 if (endvertex < surfaceendvertex)
11331                         endvertex = surfaceendvertex;
11332                 numtriangles += surfacenumtriangles;
11333         }
11334         if (!numtriangles)
11335                 return;
11336
11337         // we now know the vertex range used, and if there are any gaps in it
11338         rsurface.batchfirstvertex = firstvertex;
11339         rsurface.batchnumvertices = endvertex - firstvertex;
11340         rsurface.batchfirsttriangle = firsttriangle;
11341         rsurface.batchnumtriangles = numtriangles;
11342
11343         // this variable holds flags for which properties have been updated that
11344         // may require regenerating vertexmesh or vertexposition arrays...
11345         needsupdate = 0;
11346
11347         // check if any dynamic vertex processing must occur
11348         dynamicvertex = false;
11349
11350         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11351                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11352         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11353         {
11354                 switch (deform->deform)
11355                 {
11356                 default:
11357                 case Q3DEFORM_PROJECTIONSHADOW:
11358                 case Q3DEFORM_TEXT0:
11359                 case Q3DEFORM_TEXT1:
11360                 case Q3DEFORM_TEXT2:
11361                 case Q3DEFORM_TEXT3:
11362                 case Q3DEFORM_TEXT4:
11363                 case Q3DEFORM_TEXT5:
11364                 case Q3DEFORM_TEXT6:
11365                 case Q3DEFORM_TEXT7:
11366                 case Q3DEFORM_NONE:
11367                         break;
11368                 case Q3DEFORM_AUTOSPRITE:
11369                         dynamicvertex = true;
11370                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11371                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11372                         break;
11373                 case Q3DEFORM_AUTOSPRITE2:
11374                         dynamicvertex = true;
11375                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11376                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11377                         break;
11378                 case Q3DEFORM_NORMAL:
11379                         dynamicvertex = true;
11380                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11381                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11382                         break;
11383                 case Q3DEFORM_WAVE:
11384                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11385                                 break; // if wavefunc is a nop, ignore this transform
11386                         dynamicvertex = true;
11387                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11388                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11389                         break;
11390                 case Q3DEFORM_BULGE:
11391                         dynamicvertex = true;
11392                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11393                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11394                         break;
11395                 case Q3DEFORM_MOVE:
11396                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11397                                 break; // if wavefunc is a nop, ignore this transform
11398                         dynamicvertex = true;
11399                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11400                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11401                         break;
11402                 }
11403         }
11404         switch(rsurface.texture->tcgen.tcgen)
11405         {
11406         default:
11407         case Q3TCGEN_TEXTURE:
11408                 break;
11409         case Q3TCGEN_LIGHTMAP:
11410                 dynamicvertex = true;
11411                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11412                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11413                 break;
11414         case Q3TCGEN_VECTOR:
11415                 dynamicvertex = true;
11416                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11417                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11418                 break;
11419         case Q3TCGEN_ENVIRONMENT:
11420                 dynamicvertex = true;
11421                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11422                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11423                 break;
11424         }
11425         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11426         {
11427                 dynamicvertex = true;
11428                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11429                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11430         }
11431
11432         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11433         {
11434                 dynamicvertex = true;
11435                 batchneed |= BATCHNEED_NOGAPS;
11436                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11437         }
11438
11439         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11440         {
11441                 dynamicvertex = true;
11442                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11443                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11444         }
11445
11446         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11447         {
11448                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11449                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11450                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11451                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11452                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11453                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11454                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11455         }
11456
11457         // when the model data has no vertex buffer (dynamic mesh), we need to
11458         // eliminate gaps
11459         if (!rsurface.modelvertexmeshbuffer)
11460                 batchneed |= BATCHNEED_NOGAPS;
11461
11462         // if needsupdate, we have to do a dynamic vertex batch for sure
11463         if (needsupdate & batchneed)
11464                 dynamicvertex = true;
11465
11466         // see if we need to build vertexmesh from arrays
11467         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11468                 dynamicvertex = true;
11469
11470         // see if we need to build vertexposition from arrays
11471         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11472                 dynamicvertex = true;
11473
11474         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11475         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11476                 dynamicvertex = true;
11477
11478         // if there is a chance of animated vertex colors, it's a dynamic batch
11479         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11480                 dynamicvertex = true;
11481
11482         rsurface.batchvertex3f = rsurface.modelvertex3f;
11483         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11484         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11485         rsurface.batchsvector3f = rsurface.modelsvector3f;
11486         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11487         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11488         rsurface.batchtvector3f = rsurface.modeltvector3f;
11489         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11490         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11491         rsurface.batchnormal3f = rsurface.modelnormal3f;
11492         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11493         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11494         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11495         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11496         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11497         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11498         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11499         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11500         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11501         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11502         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11503         rsurface.batchvertexposition = rsurface.modelvertexposition;
11504         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11505         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11506         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11507         rsurface.batchelement3i = rsurface.modelelement3i;
11508         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11509         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11510         rsurface.batchelement3s = rsurface.modelelement3s;
11511         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11512         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11513
11514         // if any dynamic vertex processing has to occur in software, we copy the
11515         // entire surface list together before processing to rebase the vertices
11516         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11517         //
11518         // if any gaps exist and we do not have a static vertex buffer, we have to
11519         // copy the surface list together to avoid wasting upload bandwidth on the
11520         // vertices in the gaps.
11521         //
11522         // if gaps exist and we have a static vertex buffer, we still have to
11523         // combine the index buffer ranges into one dynamic index buffer.
11524         //
11525         // in all cases we end up with data that can be drawn in one call.
11526
11527         if (!dynamicvertex)
11528         {
11529                 // static vertex data, just set pointers...
11530                 rsurface.batchgeneratedvertex = false;
11531                 // if there are gaps, we want to build a combined index buffer,
11532                 // otherwise use the original static buffer with an appropriate offset
11533                 if (gaps)
11534                 {
11535                         firsttriangle = 0;
11536                         numtriangles = 0;
11537                         for (i = 0;i < texturenumsurfaces;i++)
11538                         {
11539                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11540                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11541                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11542                                 numtriangles += surfacenumtriangles;
11543                         }
11544                         rsurface.batchelement3i = rsurface.array_batchelement3i;
11545                         rsurface.batchelement3i_indexbuffer = NULL;
11546                         rsurface.batchelement3i_bufferoffset = 0;
11547                         rsurface.batchelement3s = NULL;
11548                         rsurface.batchelement3s_indexbuffer = NULL;
11549                         rsurface.batchelement3s_bufferoffset = 0;
11550                         if (endvertex <= 65536)
11551                         {
11552                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
11553                                 for (i = 0;i < numtriangles*3;i++)
11554                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11555                         }
11556                         rsurface.batchfirsttriangle = firsttriangle;
11557                         rsurface.batchnumtriangles = numtriangles;
11558                 }
11559                 return;
11560         }
11561
11562         // something needs software processing, do it for real...
11563         // we only directly handle interleaved array data in this case...
11564         rsurface.batchgeneratedvertex = true;
11565
11566         // now copy the vertex data into a combined array and make an index array
11567         // (this is what Quake3 does all the time)
11568         //if (gaps || rsurface.batchfirstvertex)
11569         {
11570                 rsurface.batchvertexposition = NULL;
11571                 rsurface.batchvertexpositionbuffer = NULL;
11572                 rsurface.batchvertexmesh = NULL;
11573                 rsurface.batchvertexmeshbuffer = NULL;
11574                 rsurface.batchvertex3f = NULL;
11575                 rsurface.batchvertex3f_vertexbuffer = NULL;
11576                 rsurface.batchvertex3f_bufferoffset = 0;
11577                 rsurface.batchsvector3f = NULL;
11578                 rsurface.batchsvector3f_vertexbuffer = NULL;
11579                 rsurface.batchsvector3f_bufferoffset = 0;
11580                 rsurface.batchtvector3f = NULL;
11581                 rsurface.batchtvector3f_vertexbuffer = NULL;
11582                 rsurface.batchtvector3f_bufferoffset = 0;
11583                 rsurface.batchnormal3f = NULL;
11584                 rsurface.batchnormal3f_vertexbuffer = NULL;
11585                 rsurface.batchnormal3f_bufferoffset = 0;
11586                 rsurface.batchlightmapcolor4f = NULL;
11587                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11588                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11589                 rsurface.batchtexcoordtexture2f = NULL;
11590                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11591                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11592                 rsurface.batchtexcoordlightmap2f = NULL;
11593                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11594                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11595                 rsurface.batchelement3i = rsurface.array_batchelement3i;
11596                 rsurface.batchelement3i_indexbuffer = NULL;
11597                 rsurface.batchelement3i_bufferoffset = 0;
11598                 rsurface.batchelement3s = NULL;
11599                 rsurface.batchelement3s_indexbuffer = NULL;
11600                 rsurface.batchelement3s_bufferoffset = 0;
11601                 // we'll only be setting up certain arrays as needed
11602                 if (batchneed & BATCHNEED_VERTEXPOSITION)
11603                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11604                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11605                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11606                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11607                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11608                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11609                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11610                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11611                 {
11612                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11613                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11614                 }
11615                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11616                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11617                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11618                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11619                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11620                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11621                 numvertices = 0;
11622                 numtriangles = 0;
11623                 for (i = 0;i < texturenumsurfaces;i++)
11624                 {
11625                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11626                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11627                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11628                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11629                         // copy only the data requested
11630                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11631                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11632                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11633                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11634                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11635                         {
11636                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11637                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11638                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11639                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11640                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11641                                 {
11642                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11643                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11644                                 }
11645                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11646                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11647                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11648                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11649                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11650                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11651                         }
11652                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11653                         numvertices += surfacenumvertices;
11654                         numtriangles += surfacenumtriangles;
11655                 }
11656
11657                 // generate a 16bit index array as well if possible
11658                 // (in general, dynamic batches fit)
11659                 if (numvertices <= 65536)
11660                 {
11661                         rsurface.batchelement3s = rsurface.array_batchelement3s;
11662                         for (i = 0;i < numtriangles*3;i++)
11663                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11664                 }
11665
11666                 // since we've copied everything, the batch now starts at 0
11667                 rsurface.batchfirstvertex = 0;
11668                 rsurface.batchnumvertices = numvertices;
11669                 rsurface.batchfirsttriangle = 0;
11670                 rsurface.batchnumtriangles = numtriangles;
11671         }
11672
11673         // q1bsp surfaces rendered in vertex color mode have to have colors
11674         // calculated based on lightstyles
11675         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11676         {
11677                 // generate color arrays for the surfaces in this list
11678                 int c[4];
11679                 int scale;
11680                 int size3;
11681                 const int *offsets;
11682                 const unsigned char *lm;
11683                 numvertices = 0;
11684                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11685                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11686                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11687                 for (i = 0;i < texturenumsurfaces;i++)
11688                 {
11689                         surface = texturesurfacelist[i];
11690                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11691                         surfacenumvertices = surface->num_vertices;
11692                         if (surface->lightmapinfo->samples)
11693                         {
11694                                 for (j = 0;j < surfacenumvertices;j++)
11695                                 {
11696                                         lm = surface->lightmapinfo->samples + offsets[j];
11697                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11698                                         VectorScale(lm, scale, c);
11699                                         if (surface->lightmapinfo->styles[1] != 255)
11700                                         {
11701                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11702                                                 lm += size3;
11703                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11704                                                 VectorMA(c, scale, lm, c);
11705                                                 if (surface->lightmapinfo->styles[2] != 255)
11706                                                 {
11707                                                         lm += size3;
11708                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11709                                                         VectorMA(c, scale, lm, c);
11710                                                         if (surface->lightmapinfo->styles[3] != 255)
11711                                                         {
11712                                                                 lm += size3;
11713                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11714                                                                 VectorMA(c, scale, lm, c);
11715                                                         }
11716                                                 }
11717                                         }
11718                                         c[0] >>= 15;
11719                                         c[1] >>= 15;
11720                                         c[2] >>= 15;
11721                                         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);
11722                                         numvertices++;
11723                                 }
11724                         }
11725                         else
11726                         {
11727                                 for (j = 0;j < surfacenumvertices;j++)
11728                                 {
11729                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11730                                         numvertices++;
11731                                 }
11732                         }
11733                 }
11734         }
11735
11736         // if vertices are deformed (sprite flares and things in maps, possibly
11737         // water waves, bulges and other deformations), modify the copied vertices
11738         // in place
11739         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11740         {
11741                 switch (deform->deform)
11742                 {
11743                 default:
11744                 case Q3DEFORM_PROJECTIONSHADOW:
11745                 case Q3DEFORM_TEXT0:
11746                 case Q3DEFORM_TEXT1:
11747                 case Q3DEFORM_TEXT2:
11748                 case Q3DEFORM_TEXT3:
11749                 case Q3DEFORM_TEXT4:
11750                 case Q3DEFORM_TEXT5:
11751                 case Q3DEFORM_TEXT6:
11752                 case Q3DEFORM_TEXT7:
11753                 case Q3DEFORM_NONE:
11754                         break;
11755                 case Q3DEFORM_AUTOSPRITE:
11756                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11757                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11758                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11759                         VectorNormalize(newforward);
11760                         VectorNormalize(newright);
11761                         VectorNormalize(newup);
11762                         // a single autosprite surface can contain multiple sprites...
11763                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11764                         {
11765                                 VectorClear(center);
11766                                 for (i = 0;i < 4;i++)
11767                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11768                                 VectorScale(center, 0.25f, center);
11769                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11770                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11771                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11772                                 for (i = 0;i < 4;i++)
11773                                 {
11774                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11775                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11776                                 }
11777                         }
11778                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11779                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11780                         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);
11781                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11782                         rsurface.batchvertex3f_vertexbuffer = NULL;
11783                         rsurface.batchvertex3f_bufferoffset = 0;
11784                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11785                         rsurface.batchsvector3f_vertexbuffer = NULL;
11786                         rsurface.batchsvector3f_bufferoffset = 0;
11787                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11788                         rsurface.batchtvector3f_vertexbuffer = NULL;
11789                         rsurface.batchtvector3f_bufferoffset = 0;
11790                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11791                         rsurface.batchnormal3f_vertexbuffer = NULL;
11792                         rsurface.batchnormal3f_bufferoffset = 0;
11793                         break;
11794                 case Q3DEFORM_AUTOSPRITE2:
11795                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11796                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11797                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11798                         VectorNormalize(newforward);
11799                         VectorNormalize(newright);
11800                         VectorNormalize(newup);
11801                         {
11802                                 const float *v1, *v2;
11803                                 vec3_t start, end;
11804                                 float f, l;
11805                                 struct
11806                                 {
11807                                         float length2;
11808                                         const float *v1;
11809                                         const float *v2;
11810                                 }
11811                                 shortest[2];
11812                                 memset(shortest, 0, sizeof(shortest));
11813                                 // a single autosprite surface can contain multiple sprites...
11814                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11815                                 {
11816                                         VectorClear(center);
11817                                         for (i = 0;i < 4;i++)
11818                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11819                                         VectorScale(center, 0.25f, center);
11820                                         // find the two shortest edges, then use them to define the
11821                                         // axis vectors for rotating around the central axis
11822                                         for (i = 0;i < 6;i++)
11823                                         {
11824                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11825                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11826                                                 l = VectorDistance2(v1, v2);
11827                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11828                                                 if (v1[2] != v2[2])
11829                                                         l += (1.0f / 1024.0f);
11830                                                 if (shortest[0].length2 > l || i == 0)
11831                                                 {
11832                                                         shortest[1] = shortest[0];
11833                                                         shortest[0].length2 = l;
11834                                                         shortest[0].v1 = v1;
11835                                                         shortest[0].v2 = v2;
11836                                                 }
11837                                                 else if (shortest[1].length2 > l || i == 1)
11838                                                 {
11839                                                         shortest[1].length2 = l;
11840                                                         shortest[1].v1 = v1;
11841                                                         shortest[1].v2 = v2;
11842                                                 }
11843                                         }
11844                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11845                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11846                                         // this calculates the right vector from the shortest edge
11847                                         // and the up vector from the edge midpoints
11848                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11849                                         VectorNormalize(right);
11850                                         VectorSubtract(end, start, up);
11851                                         VectorNormalize(up);
11852                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11853                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11854                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11855                                         VectorNegate(forward, forward);
11856                                         VectorReflect(forward, 0, up, forward);
11857                                         VectorNormalize(forward);
11858                                         CrossProduct(up, forward, newright);
11859                                         VectorNormalize(newright);
11860                                         // rotate the quad around the up axis vector, this is made
11861                                         // especially easy by the fact we know the quad is flat,
11862                                         // so we only have to subtract the center position and
11863                                         // measure distance along the right vector, and then
11864                                         // multiply that by the newright vector and add back the
11865                                         // center position
11866                                         // we also need to subtract the old position to undo the
11867                                         // displacement from the center, which we do with a
11868                                         // DotProduct, the subtraction/addition of center is also
11869                                         // optimized into DotProducts here
11870                                         l = DotProduct(right, center);
11871                                         for (i = 0;i < 4;i++)
11872                                         {
11873                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11874                                                 f = DotProduct(right, v1) - l;
11875                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11876                                         }
11877                                 }
11878                         }
11879                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11880                         rsurface.batchvertex3f_vertexbuffer = NULL;
11881                         rsurface.batchvertex3f_bufferoffset = 0;
11882                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11883                         {
11884                                 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11885                                 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11886                                 rsurface.batchnormal3f_vertexbuffer = NULL;
11887                                 rsurface.batchnormal3f_bufferoffset = 0;
11888                         }
11889                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11890                         {
11891                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
11892                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11893                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11894                                 rsurface.batchsvector3f_bufferoffset = 0;
11895                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11896                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11897                                 rsurface.batchtvector3f_bufferoffset = 0;
11898                         }
11899                         break;
11900                 case Q3DEFORM_NORMAL:
11901                         // deform the normals to make reflections wavey
11902                         for (j = 0;j < rsurface.batchnumvertices;j++)
11903                         {
11904                                 float vertex[3];
11905                                 float *normal = rsurface.array_batchnormal3f + 3*j;
11906                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11907                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11908                                 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]);
11909                                 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]);
11910                                 VectorNormalize(normal);
11911                         }
11912                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11913                         rsurface.batchnormal3f_vertexbuffer = NULL;
11914                         rsurface.batchnormal3f_bufferoffset = 0;
11915                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11916                         {
11917                                 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);
11918                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11919                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11920                                 rsurface.batchsvector3f_bufferoffset = 0;
11921                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11922                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11923                                 rsurface.batchtvector3f_bufferoffset = 0;
11924                         }
11925                         break;
11926                 case Q3DEFORM_WAVE:
11927                         // deform vertex array to make wavey water and flags and such
11928                         waveparms[0] = deform->waveparms[0];
11929                         waveparms[1] = deform->waveparms[1];
11930                         waveparms[2] = deform->waveparms[2];
11931                         waveparms[3] = deform->waveparms[3];
11932                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11933                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11934                         // this is how a divisor of vertex influence on deformation
11935                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11936                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11937                         for (j = 0;j < rsurface.batchnumvertices;j++)
11938                         {
11939                                 // if the wavefunc depends on time, evaluate it per-vertex
11940                                 if (waveparms[3])
11941                                 {
11942                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11943                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11944                                 }
11945                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11946                         }
11947                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11948                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11949                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11950                         rsurface.batchvertex3f_vertexbuffer = NULL;
11951                         rsurface.batchvertex3f_bufferoffset = 0;
11952                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11953                         rsurface.batchnormal3f_vertexbuffer = NULL;
11954                         rsurface.batchnormal3f_bufferoffset = 0;
11955                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11956                         {
11957                                 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);
11958                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11959                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11960                                 rsurface.batchsvector3f_bufferoffset = 0;
11961                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11962                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11963                                 rsurface.batchtvector3f_bufferoffset = 0;
11964                         }
11965                         break;
11966                 case Q3DEFORM_BULGE:
11967                         // deform vertex array to make the surface have moving bulges
11968                         for (j = 0;j < rsurface.batchnumvertices;j++)
11969                         {
11970                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11971                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11972                         }
11973                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11974                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11975                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11976                         rsurface.batchvertex3f_vertexbuffer = NULL;
11977                         rsurface.batchvertex3f_bufferoffset = 0;
11978                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11979                         rsurface.batchnormal3f_vertexbuffer = NULL;
11980                         rsurface.batchnormal3f_bufferoffset = 0;
11981                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11982                         {
11983                                 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);
11984                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11985                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11986                                 rsurface.batchsvector3f_bufferoffset = 0;
11987                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11988                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11989                                 rsurface.batchtvector3f_bufferoffset = 0;
11990                         }
11991                         break;
11992                 case Q3DEFORM_MOVE:
11993                         // deform vertex array
11994                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11995                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11996                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11997                         VectorScale(deform->parms, scale, waveparms);
11998                         for (j = 0;j < rsurface.batchnumvertices;j++)
11999                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
12000                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12001                         rsurface.batchvertex3f_vertexbuffer = NULL;
12002                         rsurface.batchvertex3f_bufferoffset = 0;
12003                         break;
12004                 }
12005         }
12006
12007         // generate texcoords based on the chosen texcoord source
12008         switch(rsurface.texture->tcgen.tcgen)
12009         {
12010         default:
12011         case Q3TCGEN_TEXTURE:
12012                 break;
12013         case Q3TCGEN_LIGHTMAP:
12014                 if (rsurface.batchtexcoordlightmap2f)
12015                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
12016                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12017                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12018                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12019                 break;
12020         case Q3TCGEN_VECTOR:
12021                 for (j = 0;j < rsurface.batchnumvertices;j++)
12022                 {
12023                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12024                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12025                 }
12026                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12027                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12028                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12029                 break;
12030         case Q3TCGEN_ENVIRONMENT:
12031                 // make environment reflections using a spheremap
12032                 for (j = 0;j < rsurface.batchnumvertices;j++)
12033                 {
12034                         // identical to Q3A's method, but executed in worldspace so
12035                         // carried models can be shiny too
12036
12037                         float viewer[3], d, reflected[3], worldreflected[3];
12038
12039                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12040                         // VectorNormalize(viewer);
12041
12042                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12043
12044                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12045                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12046                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12047                         // note: this is proportinal to viewer, so we can normalize later
12048
12049                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12050                         VectorNormalize(worldreflected);
12051
12052                         // note: this sphere map only uses world x and z!
12053                         // so positive and negative y will LOOK THE SAME.
12054                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12055                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12056                 }
12057                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12058                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12059                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12060                 break;
12061         }
12062         // the only tcmod that needs software vertex processing is turbulent, so
12063         // check for it here and apply the changes if needed
12064         // and we only support that as the first one
12065         // (handling a mixture of turbulent and other tcmods would be problematic
12066         //  without punting it entirely to a software path)
12067         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12068         {
12069                 amplitude = rsurface.texture->tcmods[0].parms[1];
12070                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12071                 for (j = 0;j < rsurface.batchnumvertices;j++)
12072                 {
12073                         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);
12074                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12075                 }
12076                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12077                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12078                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12079         }
12080
12081         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12082         {
12083                 // convert the modified arrays to vertex structs
12084                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
12085                 rsurface.batchvertexmeshbuffer = NULL;
12086                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12087                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12088                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12089                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12090                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12091                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12092                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12093                 {
12094                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12095                         {
12096                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12097                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12098                         }
12099                 }
12100                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12101                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12102                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12103                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12104                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12105                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12106                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12107                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12108                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12109         }
12110
12111         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
12112         {
12113                 // convert the modified arrays to vertex structs
12114                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
12115                 rsurface.batchvertexpositionbuffer = NULL;
12116                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
12117                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
12118                 else
12119                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
12120                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
12121         }
12122 }
12123
12124 void RSurf_DrawBatch(void)
12125 {
12126         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);
12127 }
12128
12129 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12130 {
12131         // pick the closest matching water plane
12132         int planeindex, vertexindex, bestplaneindex = -1;
12133         float d, bestd;
12134         vec3_t vert;
12135         const float *v;
12136         r_waterstate_waterplane_t *p;
12137         bestd = 0;
12138         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12139         {
12140                 if(p->camera_entity != rsurface.texture->camera_entity)
12141                         continue;
12142                 d = 0;
12143                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
12144                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12145                 {
12146                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
12147                         d += fabs(PlaneDiff(vert, &p->plane));
12148                 }
12149                 if (bestd > d || bestplaneindex < 0)
12150                 {
12151                         bestd = d;
12152                         bestplaneindex = planeindex;
12153                 }
12154         }
12155         return bestplaneindex;
12156 }
12157
12158 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12159 {
12160         int i;
12161         for (i = 0;i < rsurface.batchnumvertices;i++)
12162                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12163         rsurface.passcolor4f = rsurface.array_passcolor4f;
12164         rsurface.passcolor4f_vertexbuffer = 0;
12165         rsurface.passcolor4f_bufferoffset = 0;
12166 }
12167
12168 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12169 {
12170         int i;
12171         float f;
12172         const float *v;
12173         const float *c;
12174         float *c2;
12175         if (rsurface.passcolor4f)
12176         {
12177                 // generate color arrays
12178                 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)
12179                 {
12180                         f = RSurf_FogVertex(v);
12181                         c2[0] = c[0] * f;
12182                         c2[1] = c[1] * f;
12183                         c2[2] = c[2] * f;
12184                         c2[3] = c[3];
12185                 }
12186         }
12187         else
12188         {
12189                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12190                 {
12191                         f = RSurf_FogVertex(v);
12192                         c2[0] = f;
12193                         c2[1] = f;
12194                         c2[2] = f;
12195                         c2[3] = 1;
12196                 }
12197         }
12198         rsurface.passcolor4f = rsurface.array_passcolor4f;
12199         rsurface.passcolor4f_vertexbuffer = 0;
12200         rsurface.passcolor4f_bufferoffset = 0;
12201 }
12202
12203 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12204 {
12205         int i;
12206         float f;
12207         const float *v;
12208         const float *c;
12209         float *c2;
12210         if (!rsurface.passcolor4f)
12211                 return;
12212         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)
12213         {
12214                 f = RSurf_FogVertex(v);
12215                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12216                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12217                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12218                 c2[3] = c[3];
12219         }
12220         rsurface.passcolor4f = rsurface.array_passcolor4f;
12221         rsurface.passcolor4f_vertexbuffer = 0;
12222         rsurface.passcolor4f_bufferoffset = 0;
12223 }
12224
12225 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12226 {
12227         int i;
12228         const float *c;
12229         float *c2;
12230         if (!rsurface.passcolor4f)
12231                 return;
12232         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12233         {
12234                 c2[0] = c[0] * r;
12235                 c2[1] = c[1] * g;
12236                 c2[2] = c[2] * b;
12237                 c2[3] = c[3] * a;
12238         }
12239         rsurface.passcolor4f = rsurface.array_passcolor4f;
12240         rsurface.passcolor4f_vertexbuffer = 0;
12241         rsurface.passcolor4f_bufferoffset = 0;
12242 }
12243
12244 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12245 {
12246         int i;
12247         const float *c;
12248         float *c2;
12249         if (!rsurface.passcolor4f)
12250                 return;
12251         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12252         {
12253                 c2[0] = c[0] + r_refdef.scene.ambient;
12254                 c2[1] = c[1] + r_refdef.scene.ambient;
12255                 c2[2] = c[2] + r_refdef.scene.ambient;
12256                 c2[3] = c[3];
12257         }
12258         rsurface.passcolor4f = rsurface.array_passcolor4f;
12259         rsurface.passcolor4f_vertexbuffer = 0;
12260         rsurface.passcolor4f_bufferoffset = 0;
12261 }
12262
12263 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12264 {
12265         // TODO: optimize
12266         rsurface.passcolor4f = NULL;
12267         rsurface.passcolor4f_vertexbuffer = 0;
12268         rsurface.passcolor4f_bufferoffset = 0;
12269         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12270         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12271         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12272         GL_Color(r, g, b, a);
12273         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12274         RSurf_DrawBatch();
12275 }
12276
12277 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12278 {
12279         // TODO: optimize applyfog && applycolor case
12280         // just apply fog if necessary, and tint the fog color array if necessary
12281         rsurface.passcolor4f = NULL;
12282         rsurface.passcolor4f_vertexbuffer = 0;
12283         rsurface.passcolor4f_bufferoffset = 0;
12284         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12285         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12286         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12287         GL_Color(r, g, b, a);
12288         RSurf_DrawBatch();
12289 }
12290
12291 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12292 {
12293         // TODO: optimize
12294         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12295         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12296         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12297         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12298         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12299         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12300         GL_Color(r, g, b, a);
12301         RSurf_DrawBatch();
12302 }
12303
12304 static void RSurf_DrawBatch_GL11_ClampColor(void)
12305 {
12306         int i;
12307         const float *c1;
12308         float *c2;
12309         if (!rsurface.passcolor4f)
12310                 return;
12311         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12312         {
12313                 c2[0] = bound(0.0f, c1[0], 1.0f);
12314                 c2[1] = bound(0.0f, c1[1], 1.0f);
12315                 c2[2] = bound(0.0f, c1[2], 1.0f);
12316                 c2[3] = bound(0.0f, c1[3], 1.0f);
12317         }
12318 }
12319
12320 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12321 {
12322         int i;
12323         float f;
12324         const float *v;
12325         const float *n;
12326         float *c;
12327         //vec3_t eyedir;
12328
12329         // fake shading
12330         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)
12331         {
12332                 f = -DotProduct(r_refdef.view.forward, n);
12333                 f = max(0, f);
12334                 f = f * 0.85 + 0.15; // work around so stuff won't get black
12335                 f *= r_refdef.lightmapintensity;
12336                 Vector4Set(c, f, f, f, 1);
12337         }
12338
12339         rsurface.passcolor4f = rsurface.array_passcolor4f;
12340         rsurface.passcolor4f_vertexbuffer = 0;
12341         rsurface.passcolor4f_bufferoffset = 0;
12342 }
12343
12344 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12345 {
12346         RSurf_DrawBatch_GL11_ApplyFakeLight();
12347         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12348         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12349         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12350         GL_Color(r, g, b, a);
12351         RSurf_DrawBatch();
12352 }
12353
12354 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12355 {
12356         int i;
12357         float f;
12358         float alpha;
12359         const float *v;
12360         const float *n;
12361         float *c;
12362         vec3_t ambientcolor;
12363         vec3_t diffusecolor;
12364         vec3_t lightdir;
12365         // TODO: optimize
12366         // model lighting
12367         VectorCopy(rsurface.modellight_lightdir, lightdir);
12368         f = 0.5f * r_refdef.lightmapintensity;
12369         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12370         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12371         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12372         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12373         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12374         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12375         alpha = *a;
12376         if (VectorLength2(diffusecolor) > 0)
12377         {
12378                 // q3-style directional shading
12379                 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)
12380                 {
12381                         if ((f = DotProduct(n, lightdir)) > 0)
12382                                 VectorMA(ambientcolor, f, diffusecolor, c);
12383                         else
12384                                 VectorCopy(ambientcolor, c);
12385                         c[3] = alpha;
12386                 }
12387                 *r = 1;
12388                 *g = 1;
12389                 *b = 1;
12390                 *a = 1;
12391                 rsurface.passcolor4f = rsurface.array_passcolor4f;
12392                 rsurface.passcolor4f_vertexbuffer = 0;
12393                 rsurface.passcolor4f_bufferoffset = 0;
12394                 *applycolor = false;
12395         }
12396         else
12397         {
12398                 *r = ambientcolor[0];
12399                 *g = ambientcolor[1];
12400                 *b = ambientcolor[2];
12401                 rsurface.passcolor4f = NULL;
12402                 rsurface.passcolor4f_vertexbuffer = 0;
12403                 rsurface.passcolor4f_bufferoffset = 0;
12404         }
12405 }
12406
12407 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12408 {
12409         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12410         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12411         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12412         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12413         GL_Color(r, g, b, a);
12414         RSurf_DrawBatch();
12415 }
12416
12417 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12418 {
12419         int i;
12420         float f;
12421         const float *v;
12422         float *c;
12423         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12424         {
12425                 f = 1 - RSurf_FogVertex(v);
12426                 c[0] = r;
12427                 c[1] = g;
12428                 c[2] = b;
12429                 c[3] = f * a;
12430         }
12431 }
12432
12433 void RSurf_SetupDepthAndCulling(void)
12434 {
12435         // submodels are biased to avoid z-fighting with world surfaces that they
12436         // may be exactly overlapping (avoids z-fighting artifacts on certain
12437         // doors and things in Quake maps)
12438         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12439         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12440         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12441         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12442 }
12443
12444 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12445 {
12446         // transparent sky would be ridiculous
12447         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12448                 return;
12449         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12450         skyrenderlater = true;
12451         RSurf_SetupDepthAndCulling();
12452         GL_DepthMask(true);
12453         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12454         // skymasking on them, and Quake3 never did sky masking (unlike
12455         // software Quake and software Quake2), so disable the sky masking
12456         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12457         // and skymasking also looks very bad when noclipping outside the
12458         // level, so don't use it then either.
12459         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12460         {
12461                 R_Mesh_ResetTextureState();
12462                 if (skyrendermasked)
12463                 {
12464                         R_SetupShader_DepthOrShadow();
12465                         // depth-only (masking)
12466                         GL_ColorMask(0,0,0,0);
12467                         // just to make sure that braindead drivers don't draw
12468                         // anything despite that colormask...
12469                         GL_BlendFunc(GL_ZERO, GL_ONE);
12470                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12471                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12472                 }
12473                 else
12474                 {
12475                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12476                         // fog sky
12477                         GL_BlendFunc(GL_ONE, GL_ZERO);
12478                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12479                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12480                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12481                 }
12482                 RSurf_DrawBatch();
12483                 if (skyrendermasked)
12484                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12485         }
12486         R_Mesh_ResetTextureState();
12487         GL_Color(1, 1, 1, 1);
12488 }
12489
12490 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12491 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12492 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12493 {
12494         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12495                 return;
12496         if (prepass)
12497         {
12498                 // render screenspace normalmap to texture
12499                 GL_DepthMask(true);
12500                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12501                 RSurf_DrawBatch();
12502                 return;
12503         }
12504
12505         // bind lightmap texture
12506
12507         // water/refraction/reflection/camera surfaces have to be handled specially
12508         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12509         {
12510                 int start, end, startplaneindex;
12511                 for (start = 0;start < texturenumsurfaces;start = end)
12512                 {
12513                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12514                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12515                                 ;
12516                         // now that we have a batch using the same planeindex, render it
12517                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12518                         {
12519                                 // render water or distortion background
12520                                 GL_DepthMask(true);
12521                                 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));
12522                                 RSurf_DrawBatch();
12523                                 // blend surface on top
12524                                 GL_DepthMask(false);
12525                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12526                                 RSurf_DrawBatch();
12527                         }
12528                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12529                         {
12530                                 // render surface with reflection texture as input
12531                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12532                                 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));
12533                                 RSurf_DrawBatch();
12534                         }
12535                 }
12536                 return;
12537         }
12538
12539         // render surface batch normally
12540         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12541         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12542         RSurf_DrawBatch();
12543 }
12544
12545 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12546 {
12547         // OpenGL 1.3 path - anything not completely ancient
12548         qboolean applycolor;
12549         qboolean applyfog;
12550         int layerindex;
12551         const texturelayer_t *layer;
12552         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);
12553         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12554
12555         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12556         {
12557                 vec4_t layercolor;
12558                 int layertexrgbscale;
12559                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12560                 {
12561                         if (layerindex == 0)
12562                                 GL_AlphaTest(true);
12563                         else
12564                         {
12565                                 GL_AlphaTest(false);
12566                                 GL_DepthFunc(GL_EQUAL);
12567                         }
12568                 }
12569                 GL_DepthMask(layer->depthmask && writedepth);
12570                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12571                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12572                 {
12573                         layertexrgbscale = 4;
12574                         VectorScale(layer->color, 0.25f, layercolor);
12575                 }
12576                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12577                 {
12578                         layertexrgbscale = 2;
12579                         VectorScale(layer->color, 0.5f, layercolor);
12580                 }
12581                 else
12582                 {
12583                         layertexrgbscale = 1;
12584                         VectorScale(layer->color, 1.0f, layercolor);
12585                 }
12586                 layercolor[3] = layer->color[3];
12587                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12588                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12589                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12590                 switch (layer->type)
12591                 {
12592                 case TEXTURELAYERTYPE_LITTEXTURE:
12593                         // single-pass lightmapped texture with 2x rgbscale
12594                         R_Mesh_TexBind(0, r_texture_white);
12595                         R_Mesh_TexMatrix(0, NULL);
12596                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12597                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12598                         R_Mesh_TexBind(1, layer->texture);
12599                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12600                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12601                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12602                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12603                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12604                         else if (FAKELIGHT_ENABLED)
12605                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12606                         else if (rsurface.uselightmaptexture)
12607                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12608                         else
12609                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12610                         break;
12611                 case TEXTURELAYERTYPE_TEXTURE:
12612                         // singletexture unlit texture with transparency support
12613                         R_Mesh_TexBind(0, layer->texture);
12614                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12615                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12616                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12617                         R_Mesh_TexBind(1, 0);
12618                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12619                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12620                         break;
12621                 case TEXTURELAYERTYPE_FOG:
12622                         // singletexture fogging
12623                         if (layer->texture)
12624                         {
12625                                 R_Mesh_TexBind(0, layer->texture);
12626                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12627                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12628                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12629                         }
12630                         else
12631                         {
12632                                 R_Mesh_TexBind(0, 0);
12633                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12634                         }
12635                         R_Mesh_TexBind(1, 0);
12636                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12637                         // generate a color array for the fog pass
12638                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12639                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12640                         RSurf_DrawBatch();
12641                         break;
12642                 default:
12643                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12644                 }
12645         }
12646         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12647         {
12648                 GL_DepthFunc(GL_LEQUAL);
12649                 GL_AlphaTest(false);
12650         }
12651 }
12652
12653 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12654 {
12655         // OpenGL 1.1 - crusty old voodoo path
12656         qboolean applyfog;
12657         int layerindex;
12658         const texturelayer_t *layer;
12659         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);
12660         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12661
12662         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12663         {
12664                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12665                 {
12666                         if (layerindex == 0)
12667                                 GL_AlphaTest(true);
12668                         else
12669                         {
12670                                 GL_AlphaTest(false);
12671                                 GL_DepthFunc(GL_EQUAL);
12672                         }
12673                 }
12674                 GL_DepthMask(layer->depthmask && writedepth);
12675                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12676                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12677                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12678                 switch (layer->type)
12679                 {
12680                 case TEXTURELAYERTYPE_LITTEXTURE:
12681                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12682                         {
12683                                 // two-pass lit texture with 2x rgbscale
12684                                 // first the lightmap pass
12685                                 R_Mesh_TexBind(0, r_texture_white);
12686                                 R_Mesh_TexMatrix(0, NULL);
12687                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12688                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12689                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12690                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12691                                 else if (FAKELIGHT_ENABLED)
12692                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12693                                 else if (rsurface.uselightmaptexture)
12694                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12695                                 else
12696                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12697                                 // then apply the texture to it
12698                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12699                                 R_Mesh_TexBind(0, layer->texture);
12700                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12701                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12702                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12703                                 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);
12704                         }
12705                         else
12706                         {
12707                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12708                                 R_Mesh_TexBind(0, layer->texture);
12709                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12710                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12711                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12712                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12713                                         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);
12714                                 else
12715                                         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);
12716                         }
12717                         break;
12718                 case TEXTURELAYERTYPE_TEXTURE:
12719                         // singletexture unlit texture with transparency support
12720                         R_Mesh_TexBind(0, layer->texture);
12721                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12722                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12723                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12724                         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);
12725                         break;
12726                 case TEXTURELAYERTYPE_FOG:
12727                         // singletexture fogging
12728                         if (layer->texture)
12729                         {
12730                                 R_Mesh_TexBind(0, layer->texture);
12731                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12732                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12733                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12734                         }
12735                         else
12736                         {
12737                                 R_Mesh_TexBind(0, 0);
12738                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12739                         }
12740                         // generate a color array for the fog pass
12741                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12742                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12743                         RSurf_DrawBatch();
12744                         break;
12745                 default:
12746                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12747                 }
12748         }
12749         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12750         {
12751                 GL_DepthFunc(GL_LEQUAL);
12752                 GL_AlphaTest(false);
12753         }
12754 }
12755
12756 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12757 {
12758         int vi;
12759         int j;
12760         r_vertexgeneric_t *batchvertex;
12761         float c[4];
12762
12763         GL_AlphaTest(false);
12764         R_Mesh_ResetTextureState();
12765         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12766
12767         if(rsurface.texture && rsurface.texture->currentskinframe)
12768         {
12769                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12770                 c[3] *= rsurface.texture->currentalpha;
12771         }
12772         else
12773         {
12774                 c[0] = 1;
12775                 c[1] = 0;
12776                 c[2] = 1;
12777                 c[3] = 1;
12778         }
12779
12780         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12781         {
12782                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12783                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12784                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12785         }
12786
12787         // brighten it up (as texture value 127 means "unlit")
12788         c[0] *= 2 * r_refdef.view.colorscale;
12789         c[1] *= 2 * r_refdef.view.colorscale;
12790         c[2] *= 2 * r_refdef.view.colorscale;
12791
12792         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12793                 c[3] *= r_wateralpha.value;
12794
12795         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12796         {
12797                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12798                 GL_DepthMask(false);
12799         }
12800         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12801         {
12802                 GL_BlendFunc(GL_ONE, GL_ONE);
12803                 GL_DepthMask(false);
12804         }
12805         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12806         {
12807                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12808                 GL_DepthMask(false);
12809         }
12810         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12811         {
12812                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12813                 GL_DepthMask(false);
12814         }
12815         else
12816         {
12817                 GL_BlendFunc(GL_ONE, GL_ZERO);
12818                 GL_DepthMask(writedepth);
12819         }
12820
12821         if (r_showsurfaces.integer == 3)
12822         {
12823                 rsurface.passcolor4f = NULL;
12824
12825                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12826                 {
12827                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12828
12829                         rsurface.passcolor4f = NULL;
12830                         rsurface.passcolor4f_vertexbuffer = 0;
12831                         rsurface.passcolor4f_bufferoffset = 0;
12832                 }
12833                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12834                 {
12835                         qboolean applycolor = true;
12836                         float one = 1.0;
12837
12838                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12839
12840                         r_refdef.lightmapintensity = 1;
12841                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12842                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12843                 }
12844                 else if (FAKELIGHT_ENABLED)
12845                 {
12846                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12847
12848                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
12849                         RSurf_DrawBatch_GL11_ApplyFakeLight();
12850                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12851                 }
12852                 else
12853                 {
12854                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12855
12856                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12857                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12858                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12859                 }
12860
12861                 if(!rsurface.passcolor4f)
12862                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12863
12864                 RSurf_DrawBatch_GL11_ApplyAmbient();
12865                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12866                 if(r_refdef.fogenabled)
12867                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12868                 RSurf_DrawBatch_GL11_ClampColor();
12869
12870                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12871                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12872                 RSurf_DrawBatch();
12873         }
12874         else if (!r_refdef.view.showdebug)
12875         {
12876                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12877                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12878                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12879                 {
12880                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12881                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12882                 }
12883                 R_Mesh_PrepareVertices_Generic_Unlock();
12884                 RSurf_DrawBatch();
12885         }
12886         else if (r_showsurfaces.integer == 4)
12887         {
12888                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12889                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12890                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12891                 {
12892                         unsigned char c = vi << 3;
12893                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12894                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12895                 }
12896                 R_Mesh_PrepareVertices_Generic_Unlock();
12897                 RSurf_DrawBatch();
12898         }
12899         else if (r_showsurfaces.integer == 2)
12900         {
12901                 const int *e;
12902                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12903                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12904                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12905                 {
12906                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12907                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12908                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12909                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12910                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12911                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12912                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12913                 }
12914                 R_Mesh_PrepareVertices_Generic_Unlock();
12915                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12916         }
12917         else
12918         {
12919                 int texturesurfaceindex;
12920                 int k;
12921                 const msurface_t *surface;
12922                 unsigned char surfacecolor4ub[4];
12923                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12924                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12925                 vi = 0;
12926                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12927                 {
12928                         surface = texturesurfacelist[texturesurfaceindex];
12929                         k = (int)(((size_t)surface) / sizeof(msurface_t));
12930                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12931                         for (j = 0;j < surface->num_vertices;j++)
12932                         {
12933                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12934                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12935                                 vi++;
12936                         }
12937                 }
12938                 R_Mesh_PrepareVertices_Generic_Unlock();
12939                 RSurf_DrawBatch();
12940         }
12941 }
12942
12943 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12944 {
12945         CHECKGLERROR
12946         RSurf_SetupDepthAndCulling();
12947         if (r_showsurfaces.integer)
12948         {
12949                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12950                 return;
12951         }
12952         switch (vid.renderpath)
12953         {
12954         case RENDERPATH_GL20:
12955         case RENDERPATH_CGGL:
12956         case RENDERPATH_D3D9:
12957         case RENDERPATH_D3D10:
12958         case RENDERPATH_D3D11:
12959                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12960                 break;
12961         case RENDERPATH_GL13:
12962                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12963                 break;
12964         case RENDERPATH_GL11:
12965                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12966                 break;
12967         }
12968         CHECKGLERROR
12969 }
12970
12971 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12972 {
12973         CHECKGLERROR
12974         RSurf_SetupDepthAndCulling();
12975         if (r_showsurfaces.integer)
12976         {
12977                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12978                 return;
12979         }
12980         switch (vid.renderpath)
12981         {
12982         case RENDERPATH_GL20:
12983         case RENDERPATH_CGGL:
12984         case RENDERPATH_D3D9:
12985         case RENDERPATH_D3D10:
12986         case RENDERPATH_D3D11:
12987                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12988                 break;
12989         case RENDERPATH_GL13:
12990                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12991                 break;
12992         case RENDERPATH_GL11:
12993                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12994                 break;
12995         }
12996         CHECKGLERROR
12997 }
12998
12999 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13000 {
13001         int i, j;
13002         int texturenumsurfaces, endsurface;
13003         texture_t *texture;
13004         const msurface_t *surface;
13005 #define MAXBATCH_TRANSPARENTSURFACES 256
13006         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13007
13008         // if the model is static it doesn't matter what value we give for
13009         // wantnormals and wanttangents, so this logic uses only rules applicable
13010         // to a model, knowing that they are meaningless otherwise
13011         if (ent == r_refdef.scene.worldentity)
13012                 RSurf_ActiveWorldEntity();
13013         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13014                 RSurf_ActiveModelEntity(ent, false, false, false);
13015         else
13016         {
13017                 switch (vid.renderpath)
13018                 {
13019                 case RENDERPATH_GL20:
13020                 case RENDERPATH_CGGL:
13021                 case RENDERPATH_D3D9:
13022                 case RENDERPATH_D3D10:
13023                 case RENDERPATH_D3D11:
13024                         RSurf_ActiveModelEntity(ent, true, true, false);
13025                         break;
13026                 case RENDERPATH_GL13:
13027                 case RENDERPATH_GL11:
13028                         RSurf_ActiveModelEntity(ent, true, false, false);
13029                         break;
13030                 }
13031         }
13032
13033         if (r_transparentdepthmasking.integer)
13034         {
13035                 qboolean setup = false;
13036                 for (i = 0;i < numsurfaces;i = j)
13037                 {
13038                         j = i + 1;
13039                         surface = rsurface.modelsurfaces + surfacelist[i];
13040                         texture = surface->texture;
13041                         rsurface.texture = R_GetCurrentTexture(texture);
13042                         rsurface.lightmaptexture = NULL;
13043                         rsurface.deluxemaptexture = NULL;
13044                         rsurface.uselightmaptexture = false;
13045                         // scan ahead until we find a different texture
13046                         endsurface = min(i + 1024, numsurfaces);
13047                         texturenumsurfaces = 0;
13048                         texturesurfacelist[texturenumsurfaces++] = surface;
13049                         for (;j < endsurface;j++)
13050                         {
13051                                 surface = rsurface.modelsurfaces + surfacelist[j];
13052                                 if (texture != surface->texture)
13053                                         break;
13054                                 texturesurfacelist[texturenumsurfaces++] = surface;
13055                         }
13056                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13057                                 continue;
13058                         // render the range of surfaces as depth
13059                         if (!setup)
13060                         {
13061                                 setup = true;
13062                                 GL_ColorMask(0,0,0,0);
13063                                 GL_Color(1,1,1,1);
13064                                 GL_DepthTest(true);
13065                                 GL_BlendFunc(GL_ONE, GL_ZERO);
13066                                 GL_DepthMask(true);
13067                                 GL_AlphaTest(false);
13068                                 R_Mesh_ResetTextureState();
13069                                 R_SetupShader_DepthOrShadow();
13070                         }
13071                         RSurf_SetupDepthAndCulling();
13072                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13073                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13074                         RSurf_DrawBatch();
13075                 }
13076                 if (setup)
13077                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13078         }
13079
13080         for (i = 0;i < numsurfaces;i = j)
13081         {
13082                 j = i + 1;
13083                 surface = rsurface.modelsurfaces + surfacelist[i];
13084                 texture = surface->texture;
13085                 rsurface.texture = R_GetCurrentTexture(texture);
13086                 // scan ahead until we find a different texture
13087                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13088                 texturenumsurfaces = 0;
13089                 texturesurfacelist[texturenumsurfaces++] = surface;
13090                 if(FAKELIGHT_ENABLED)
13091                 {
13092                         rsurface.lightmaptexture = NULL;
13093                         rsurface.deluxemaptexture = NULL;
13094                         rsurface.uselightmaptexture = false;
13095                         for (;j < endsurface;j++)
13096                         {
13097                                 surface = rsurface.modelsurfaces + surfacelist[j];
13098                                 if (texture != surface->texture)
13099                                         break;
13100                                 texturesurfacelist[texturenumsurfaces++] = surface;
13101                         }
13102                 }
13103                 else
13104                 {
13105                         rsurface.lightmaptexture = surface->lightmaptexture;
13106                         rsurface.deluxemaptexture = surface->deluxemaptexture;
13107                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13108                         for (;j < endsurface;j++)
13109                         {
13110                                 surface = rsurface.modelsurfaces + surfacelist[j];
13111                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13112                                         break;
13113                                 texturesurfacelist[texturenumsurfaces++] = surface;
13114                         }
13115                 }
13116                 // render the range of surfaces
13117                 if (ent == r_refdef.scene.worldentity)
13118                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13119                 else
13120                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13121         }
13122         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13123         GL_AlphaTest(false);
13124 }
13125
13126 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13127 {
13128         // transparent surfaces get pushed off into the transparent queue
13129         int surfacelistindex;
13130         const msurface_t *surface;
13131         vec3_t tempcenter, center;
13132         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13133         {
13134                 surface = texturesurfacelist[surfacelistindex];
13135                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13136                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13137                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13138                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13139                 if (queueentity->transparent_offset) // transparent offset
13140                 {
13141                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13142                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13143                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13144                 }
13145                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13146         }
13147 }
13148
13149 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13150 {
13151         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13152                 return;
13153         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13154                 return;
13155         RSurf_SetupDepthAndCulling();
13156         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13157         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13158         RSurf_DrawBatch();
13159 }
13160
13161 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13162 {
13163         const entity_render_t *queueentity = r_refdef.scene.worldentity;
13164         CHECKGLERROR
13165         if (depthonly)
13166                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13167         else if (prepass)
13168         {
13169                 if (!rsurface.texture->currentnumlayers)
13170                         return;
13171                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13172                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13173                 else
13174                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13175         }
13176         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13177                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13178         else if (!rsurface.texture->currentnumlayers)
13179                 return;
13180         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13181         {
13182                 // in the deferred case, transparent surfaces were queued during prepass
13183                 if (!r_shadow_usingdeferredprepass)
13184                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13185         }
13186         else
13187         {
13188                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13189                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13190         }
13191         CHECKGLERROR
13192 }
13193
13194 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13195 {
13196         int i, j;
13197         texture_t *texture;
13198         // break the surface list down into batches by texture and use of lightmapping
13199         for (i = 0;i < numsurfaces;i = j)
13200         {
13201                 j = i + 1;
13202                 // texture is the base texture pointer, rsurface.texture is the
13203                 // current frame/skin the texture is directing us to use (for example
13204                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13205                 // use skin 1 instead)
13206                 texture = surfacelist[i]->texture;
13207                 rsurface.texture = R_GetCurrentTexture(texture);
13208                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13209                 {
13210                         // if this texture is not the kind we want, skip ahead to the next one
13211                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13212                                 ;
13213                         continue;
13214                 }
13215                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13216                 {
13217                         rsurface.lightmaptexture = NULL;
13218                         rsurface.deluxemaptexture = NULL;
13219                         rsurface.uselightmaptexture = false;
13220                         // simply scan ahead until we find a different texture or lightmap state
13221                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13222                                 ;
13223                 }
13224                 else
13225                 {
13226                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13227                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13228                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13229                         // simply scan ahead until we find a different texture or lightmap state
13230                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13231                                 ;
13232                 }
13233                 // render the range of surfaces
13234                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13235         }
13236 }
13237
13238 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13239 {
13240         CHECKGLERROR
13241         if (depthonly)
13242                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13243         else if (prepass)
13244         {
13245                 if (!rsurface.texture->currentnumlayers)
13246                         return;
13247                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13248                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13249                 else
13250                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13251         }
13252         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13253                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13254         else if (!rsurface.texture->currentnumlayers)
13255                 return;
13256         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13257         {
13258                 // in the deferred case, transparent surfaces were queued during prepass
13259                 if (!r_shadow_usingdeferredprepass)
13260                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13261         }
13262         else
13263         {
13264                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13265                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13266         }
13267         CHECKGLERROR
13268 }
13269
13270 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13271 {
13272         int i, j;
13273         texture_t *texture;
13274         // break the surface list down into batches by texture and use of lightmapping
13275         for (i = 0;i < numsurfaces;i = j)
13276         {
13277                 j = i + 1;
13278                 // texture is the base texture pointer, rsurface.texture is the
13279                 // current frame/skin the texture is directing us to use (for example
13280                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13281                 // use skin 1 instead)
13282                 texture = surfacelist[i]->texture;
13283                 rsurface.texture = R_GetCurrentTexture(texture);
13284                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13285                 {
13286                         // if this texture is not the kind we want, skip ahead to the next one
13287                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13288                                 ;
13289                         continue;
13290                 }
13291                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13292                 {
13293                         rsurface.lightmaptexture = NULL;
13294                         rsurface.deluxemaptexture = NULL;
13295                         rsurface.uselightmaptexture = false;
13296                         // simply scan ahead until we find a different texture or lightmap state
13297                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13298                                 ;
13299                 }
13300                 else
13301                 {
13302                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13303                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13304                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13305                         // simply scan ahead until we find a different texture or lightmap state
13306                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13307                                 ;
13308                 }
13309                 // render the range of surfaces
13310                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13311         }
13312 }
13313
13314 float locboxvertex3f[6*4*3] =
13315 {
13316         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13317         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13318         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13319         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13320         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13321         1,0,0, 0,0,0, 0,1,0, 1,1,0
13322 };
13323
13324 unsigned short locboxelements[6*2*3] =
13325 {
13326          0, 1, 2, 0, 2, 3,
13327          4, 5, 6, 4, 6, 7,
13328          8, 9,10, 8,10,11,
13329         12,13,14, 12,14,15,
13330         16,17,18, 16,18,19,
13331         20,21,22, 20,22,23
13332 };
13333
13334 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13335 {
13336         int i, j;
13337         cl_locnode_t *loc = (cl_locnode_t *)ent;
13338         vec3_t mins, size;
13339         float vertex3f[6*4*3];
13340         CHECKGLERROR
13341         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13342         GL_DepthMask(false);
13343         GL_DepthRange(0, 1);
13344         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13345         GL_DepthTest(true);
13346         GL_CullFace(GL_NONE);
13347         R_EntityMatrix(&identitymatrix);
13348
13349         R_Mesh_ResetTextureState();
13350
13351         i = surfacelist[0];
13352         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13353                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13354                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13355                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13356
13357         if (VectorCompare(loc->mins, loc->maxs))
13358         {
13359                 VectorSet(size, 2, 2, 2);
13360                 VectorMA(loc->mins, -0.5f, size, mins);
13361         }
13362         else
13363         {
13364                 VectorCopy(loc->mins, mins);
13365                 VectorSubtract(loc->maxs, loc->mins, size);
13366         }
13367
13368         for (i = 0;i < 6*4*3;)
13369                 for (j = 0;j < 3;j++, i++)
13370                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13371
13372         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13373         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13374         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13375 }
13376
13377 void R_DrawLocs(void)
13378 {
13379         int index;
13380         cl_locnode_t *loc, *nearestloc;
13381         vec3_t center;
13382         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13383         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13384         {
13385                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13386                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13387         }
13388 }
13389
13390 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13391 {
13392         if (decalsystem->decals)
13393                 Mem_Free(decalsystem->decals);
13394         memset(decalsystem, 0, sizeof(*decalsystem));
13395 }
13396
13397 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)
13398 {
13399         tridecal_t *decal;
13400         tridecal_t *decals;
13401         int i;
13402
13403         // expand or initialize the system
13404         if (decalsystem->maxdecals <= decalsystem->numdecals)
13405         {
13406                 decalsystem_t old = *decalsystem;
13407                 qboolean useshortelements;
13408                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13409                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13410                 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)));
13411                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13412                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13413                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13414                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13415                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13416                 if (decalsystem->numdecals)
13417                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13418                 if (old.decals)
13419                         Mem_Free(old.decals);
13420                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13421                         decalsystem->element3i[i] = i;
13422                 if (useshortelements)
13423                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13424                                 decalsystem->element3s[i] = i;
13425         }
13426
13427         // grab a decal and search for another free slot for the next one
13428         decals = decalsystem->decals;
13429         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13430         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13431                 ;
13432         decalsystem->freedecal = i;
13433         if (decalsystem->numdecals <= i)
13434                 decalsystem->numdecals = i + 1;
13435
13436         // initialize the decal
13437         decal->lived = 0;
13438         decal->triangleindex = triangleindex;
13439         decal->surfaceindex = surfaceindex;
13440         decal->decalsequence = decalsequence;
13441         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13442         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13443         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13444         decal->color4ub[0][3] = 255;
13445         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13446         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13447         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13448         decal->color4ub[1][3] = 255;
13449         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13450         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13451         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13452         decal->color4ub[2][3] = 255;
13453         decal->vertex3f[0][0] = v0[0];
13454         decal->vertex3f[0][1] = v0[1];
13455         decal->vertex3f[0][2] = v0[2];
13456         decal->vertex3f[1][0] = v1[0];
13457         decal->vertex3f[1][1] = v1[1];
13458         decal->vertex3f[1][2] = v1[2];
13459         decal->vertex3f[2][0] = v2[0];
13460         decal->vertex3f[2][1] = v2[1];
13461         decal->vertex3f[2][2] = v2[2];
13462         decal->texcoord2f[0][0] = t0[0];
13463         decal->texcoord2f[0][1] = t0[1];
13464         decal->texcoord2f[1][0] = t1[0];
13465         decal->texcoord2f[1][1] = t1[1];
13466         decal->texcoord2f[2][0] = t2[0];
13467         decal->texcoord2f[2][1] = t2[1];
13468 }
13469
13470 extern cvar_t cl_decals_bias;
13471 extern cvar_t cl_decals_models;
13472 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13473 // baseparms, parms, temps
13474 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)
13475 {
13476         int cornerindex;
13477         int index;
13478         float v[9][3];
13479         const float *vertex3f;
13480         int numpoints;
13481         float points[2][9][3];
13482         float temp[3];
13483         float tc[9][2];
13484         float f;
13485         float c[9][4];
13486         const int *e;
13487
13488         e = rsurface.modelelement3i + 3*triangleindex;
13489
13490         vertex3f = rsurface.modelvertex3f;
13491
13492         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13493         {
13494                 index = 3*e[cornerindex];
13495                 VectorCopy(vertex3f + index, v[cornerindex]);
13496         }
13497         // cull backfaces
13498         //TriangleNormal(v[0], v[1], v[2], normal);
13499         //if (DotProduct(normal, localnormal) < 0.0f)
13500         //      continue;
13501         // clip by each of the box planes formed from the projection matrix
13502         // if anything survives, we emit the decal
13503         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]);
13504         if (numpoints < 3)
13505                 return;
13506         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]);
13507         if (numpoints < 3)
13508                 return;
13509         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]);
13510         if (numpoints < 3)
13511                 return;
13512         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]);
13513         if (numpoints < 3)
13514                 return;
13515         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]);
13516         if (numpoints < 3)
13517                 return;
13518         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]);
13519         if (numpoints < 3)
13520                 return;
13521         // some part of the triangle survived, so we have to accept it...
13522         if (dynamic)
13523         {
13524                 // dynamic always uses the original triangle
13525                 numpoints = 3;
13526                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13527                 {
13528                         index = 3*e[cornerindex];
13529                         VectorCopy(vertex3f + index, v[cornerindex]);
13530                 }
13531         }
13532         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13533         {
13534                 // convert vertex positions to texcoords
13535                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13536                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13537                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13538                 // calculate distance fade from the projection origin
13539                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13540                 f = bound(0.0f, f, 1.0f);
13541                 c[cornerindex][0] = r * f;
13542                 c[cornerindex][1] = g * f;
13543                 c[cornerindex][2] = b * f;
13544                 c[cornerindex][3] = 1.0f;
13545                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13546         }
13547         if (dynamic)
13548                 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);
13549         else
13550                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13551                         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);
13552 }
13553 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)
13554 {
13555         matrix4x4_t projection;
13556         decalsystem_t *decalsystem;
13557         qboolean dynamic;
13558         dp_model_t *model;
13559         const msurface_t *surface;
13560         const msurface_t *surfaces;
13561         const int *surfacelist;
13562         const texture_t *texture;
13563         int numtriangles;
13564         int numsurfacelist;
13565         int surfacelistindex;
13566         int surfaceindex;
13567         int triangleindex;
13568         float localorigin[3];
13569         float localnormal[3];
13570         float localmins[3];
13571         float localmaxs[3];
13572         float localsize;
13573         //float normal[3];
13574         float planes[6][4];
13575         float angles[3];
13576         bih_t *bih;
13577         int bih_triangles_count;
13578         int bih_triangles[256];
13579         int bih_surfaces[256];
13580
13581         decalsystem = &ent->decalsystem;
13582         model = ent->model;
13583         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13584         {
13585                 R_DecalSystem_Reset(&ent->decalsystem);
13586                 return;
13587         }
13588
13589         if (!model->brush.data_leafs && !cl_decals_models.integer)
13590         {
13591                 if (decalsystem->model)
13592                         R_DecalSystem_Reset(decalsystem);
13593                 return;
13594         }
13595
13596         if (decalsystem->model != model)
13597                 R_DecalSystem_Reset(decalsystem);
13598         decalsystem->model = model;
13599
13600         RSurf_ActiveModelEntity(ent, false, false, false);
13601
13602         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13603         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13604         VectorNormalize(localnormal);
13605         localsize = worldsize*rsurface.inversematrixscale;
13606         localmins[0] = localorigin[0] - localsize;
13607         localmins[1] = localorigin[1] - localsize;
13608         localmins[2] = localorigin[2] - localsize;
13609         localmaxs[0] = localorigin[0] + localsize;
13610         localmaxs[1] = localorigin[1] + localsize;
13611         localmaxs[2] = localorigin[2] + localsize;
13612
13613         //VectorCopy(localnormal, planes[4]);
13614         //VectorVectors(planes[4], planes[2], planes[0]);
13615         AnglesFromVectors(angles, localnormal, NULL, false);
13616         AngleVectors(angles, planes[0], planes[2], planes[4]);
13617         VectorNegate(planes[0], planes[1]);
13618         VectorNegate(planes[2], planes[3]);
13619         VectorNegate(planes[4], planes[5]);
13620         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13621         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13622         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13623         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13624         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13625         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13626
13627 #if 1
13628 // works
13629 {
13630         matrix4x4_t forwardprojection;
13631         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13632         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13633 }
13634 #else
13635 // broken
13636 {
13637         float projectionvector[4][3];
13638         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13639         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13640         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13641         projectionvector[0][0] = planes[0][0] * ilocalsize;
13642         projectionvector[0][1] = planes[1][0] * ilocalsize;
13643         projectionvector[0][2] = planes[2][0] * ilocalsize;
13644         projectionvector[1][0] = planes[0][1] * ilocalsize;
13645         projectionvector[1][1] = planes[1][1] * ilocalsize;
13646         projectionvector[1][2] = planes[2][1] * ilocalsize;
13647         projectionvector[2][0] = planes[0][2] * ilocalsize;
13648         projectionvector[2][1] = planes[1][2] * ilocalsize;
13649         projectionvector[2][2] = planes[2][2] * ilocalsize;
13650         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13651         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13652         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13653         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13654 }
13655 #endif
13656
13657         dynamic = model->surfmesh.isanimated;
13658         numsurfacelist = model->nummodelsurfaces;
13659         surfacelist = model->sortedmodelsurfaces;
13660         surfaces = model->data_surfaces;
13661
13662         bih = NULL;
13663         bih_triangles_count = -1;
13664         if(!dynamic)
13665         {
13666                 if(model->render_bih.numleafs)
13667                         bih = &model->render_bih;
13668                 else if(model->collision_bih.numleafs)
13669                         bih = &model->collision_bih;
13670         }
13671         if(bih)
13672                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13673         if(bih_triangles_count == 0)
13674                 return;
13675         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13676                 return;
13677         if(bih_triangles_count > 0)
13678         {
13679                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13680                 {
13681                         surfaceindex = bih_surfaces[triangleindex];
13682                         surface = surfaces + surfaceindex;
13683                         texture = surface->texture;
13684                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13685                                 continue;
13686                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13687                                 continue;
13688                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13689                 }
13690         }
13691         else
13692         {
13693                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13694                 {
13695                         surfaceindex = surfacelist[surfacelistindex];
13696                         surface = surfaces + surfaceindex;
13697                         // check cull box first because it rejects more than any other check
13698                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13699                                 continue;
13700                         // skip transparent surfaces
13701                         texture = surface->texture;
13702                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13703                                 continue;
13704                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13705                                 continue;
13706                         numtriangles = surface->num_triangles;
13707                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13708                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13709                 }
13710         }
13711 }
13712
13713 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13714 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)
13715 {
13716         int renderentityindex;
13717         float worldmins[3];
13718         float worldmaxs[3];
13719         entity_render_t *ent;
13720
13721         if (!cl_decals_newsystem.integer)
13722                 return;
13723
13724         worldmins[0] = worldorigin[0] - worldsize;
13725         worldmins[1] = worldorigin[1] - worldsize;
13726         worldmins[2] = worldorigin[2] - worldsize;
13727         worldmaxs[0] = worldorigin[0] + worldsize;
13728         worldmaxs[1] = worldorigin[1] + worldsize;
13729         worldmaxs[2] = worldorigin[2] + worldsize;
13730
13731         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13732
13733         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13734         {
13735                 ent = r_refdef.scene.entities[renderentityindex];
13736                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13737                         continue;
13738
13739                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13740         }
13741 }
13742
13743 typedef struct r_decalsystem_splatqueue_s
13744 {
13745         vec3_t worldorigin;
13746         vec3_t worldnormal;
13747         float color[4];
13748         float tcrange[4];
13749         float worldsize;
13750         int decalsequence;
13751 }
13752 r_decalsystem_splatqueue_t;
13753
13754 int r_decalsystem_numqueued = 0;
13755 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13756
13757 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)
13758 {
13759         r_decalsystem_splatqueue_t *queue;
13760
13761         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13762                 return;
13763
13764         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13765         VectorCopy(worldorigin, queue->worldorigin);
13766         VectorCopy(worldnormal, queue->worldnormal);
13767         Vector4Set(queue->color, r, g, b, a);
13768         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13769         queue->worldsize = worldsize;
13770         queue->decalsequence = cl.decalsequence++;
13771 }
13772
13773 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13774 {
13775         int i;
13776         r_decalsystem_splatqueue_t *queue;
13777
13778         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13779                 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);
13780         r_decalsystem_numqueued = 0;
13781 }
13782
13783 extern cvar_t cl_decals_max;
13784 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13785 {
13786         int i;
13787         decalsystem_t *decalsystem = &ent->decalsystem;
13788         int numdecals;
13789         int killsequence;
13790         tridecal_t *decal;
13791         float frametime;
13792         float lifetime;
13793
13794         if (!decalsystem->numdecals)
13795                 return;
13796
13797         if (r_showsurfaces.integer)
13798                 return;
13799
13800         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13801         {
13802                 R_DecalSystem_Reset(decalsystem);
13803                 return;
13804         }
13805
13806         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13807         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13808
13809         if (decalsystem->lastupdatetime)
13810                 frametime = (cl.time - decalsystem->lastupdatetime);
13811         else
13812                 frametime = 0;
13813         decalsystem->lastupdatetime = cl.time;
13814         decal = decalsystem->decals;
13815         numdecals = decalsystem->numdecals;
13816
13817         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13818         {
13819                 if (decal->color4ub[0][3])
13820                 {
13821                         decal->lived += frametime;
13822                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13823                         {
13824                                 memset(decal, 0, sizeof(*decal));
13825                                 if (decalsystem->freedecal > i)
13826                                         decalsystem->freedecal = i;
13827                         }
13828                 }
13829         }
13830         decal = decalsystem->decals;
13831         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13832                 numdecals--;
13833
13834         // collapse the array by shuffling the tail decals into the gaps
13835         for (;;)
13836         {
13837                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13838                         decalsystem->freedecal++;
13839                 if (decalsystem->freedecal == numdecals)
13840                         break;
13841                 decal[decalsystem->freedecal] = decal[--numdecals];
13842         }
13843
13844         decalsystem->numdecals = numdecals;
13845
13846         if (numdecals <= 0)
13847         {
13848                 // if there are no decals left, reset decalsystem
13849                 R_DecalSystem_Reset(decalsystem);
13850         }
13851 }
13852
13853 extern skinframe_t *decalskinframe;
13854 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13855 {
13856         int i;
13857         decalsystem_t *decalsystem = &ent->decalsystem;
13858         int numdecals;
13859         tridecal_t *decal;
13860         float faderate;
13861         float alpha;
13862         float *v3f;
13863         float *c4f;
13864         float *t2f;
13865         const int *e;
13866         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13867         int numtris = 0;
13868
13869         numdecals = decalsystem->numdecals;
13870         if (!numdecals)
13871                 return;
13872
13873         if (r_showsurfaces.integer)
13874                 return;
13875
13876         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13877         {
13878                 R_DecalSystem_Reset(decalsystem);
13879                 return;
13880         }
13881
13882         // if the model is static it doesn't matter what value we give for
13883         // wantnormals and wanttangents, so this logic uses only rules applicable
13884         // to a model, knowing that they are meaningless otherwise
13885         if (ent == r_refdef.scene.worldentity)
13886                 RSurf_ActiveWorldEntity();
13887         else
13888                 RSurf_ActiveModelEntity(ent, false, false, false);
13889
13890         decalsystem->lastupdatetime = cl.time;
13891         decal = decalsystem->decals;
13892
13893         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13894
13895         // update vertex positions for animated models
13896         v3f = decalsystem->vertex3f;
13897         c4f = decalsystem->color4f;
13898         t2f = decalsystem->texcoord2f;
13899         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13900         {
13901                 if (!decal->color4ub[0][3])
13902                         continue;
13903
13904                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13905                         continue;
13906
13907                 // update color values for fading decals
13908                 if (decal->lived >= cl_decals_time.value)
13909                 {
13910                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13911                         alpha *= (1.0f/255.0f);
13912                 }
13913                 else
13914                         alpha = 1.0f/255.0f;
13915
13916                 c4f[ 0] = decal->color4ub[0][0] * alpha;
13917                 c4f[ 1] = decal->color4ub[0][1] * alpha;
13918                 c4f[ 2] = decal->color4ub[0][2] * alpha;
13919                 c4f[ 3] = 1;
13920                 c4f[ 4] = decal->color4ub[1][0] * alpha;
13921                 c4f[ 5] = decal->color4ub[1][1] * alpha;
13922                 c4f[ 6] = decal->color4ub[1][2] * alpha;
13923                 c4f[ 7] = 1;
13924                 c4f[ 8] = decal->color4ub[2][0] * alpha;
13925                 c4f[ 9] = decal->color4ub[2][1] * alpha;
13926                 c4f[10] = decal->color4ub[2][2] * alpha;
13927                 c4f[11] = 1;
13928
13929                 t2f[0] = decal->texcoord2f[0][0];
13930                 t2f[1] = decal->texcoord2f[0][1];
13931                 t2f[2] = decal->texcoord2f[1][0];
13932                 t2f[3] = decal->texcoord2f[1][1];
13933                 t2f[4] = decal->texcoord2f[2][0];
13934                 t2f[5] = decal->texcoord2f[2][1];
13935
13936                 // update vertex positions for animated models
13937                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13938                 {
13939                         e = rsurface.modelelement3i + 3*decal->triangleindex;
13940                         VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
13941                         VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
13942                         VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
13943                 }
13944                 else
13945                 {
13946                         VectorCopy(decal->vertex3f[0], v3f);
13947                         VectorCopy(decal->vertex3f[1], v3f + 3);
13948                         VectorCopy(decal->vertex3f[2], v3f + 6);
13949                 }
13950
13951                 if (r_refdef.fogenabled)
13952                 {
13953                         alpha = RSurf_FogVertex(v3f);
13954                         VectorScale(c4f, alpha, c4f);
13955                         alpha = RSurf_FogVertex(v3f + 3);
13956                         VectorScale(c4f + 4, alpha, c4f + 4);
13957                         alpha = RSurf_FogVertex(v3f + 6);
13958                         VectorScale(c4f + 8, alpha, c4f + 8);
13959                 }
13960
13961                 v3f += 9;
13962                 c4f += 12;
13963                 t2f += 6;
13964                 numtris++;
13965         }
13966
13967         if (numtris > 0)
13968         {
13969                 r_refdef.stats.drawndecals += numtris;
13970
13971                 // now render the decals all at once
13972                 // (this assumes they all use one particle font texture!)
13973                 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);
13974                 R_Mesh_ResetTextureState();
13975                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13976                 GL_DepthMask(false);
13977                 GL_DepthRange(0, 1);
13978                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13979                 GL_DepthTest(true);
13980                 GL_CullFace(GL_NONE);
13981                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13982                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13983                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13984         }
13985 }
13986
13987 static void R_DrawModelDecals(void)
13988 {
13989         int i, numdecals;
13990
13991         // fade faster when there are too many decals
13992         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13993         for (i = 0;i < r_refdef.scene.numentities;i++)
13994                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13995
13996         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13997         for (i = 0;i < r_refdef.scene.numentities;i++)
13998                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13999                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14000
14001         R_DecalSystem_ApplySplatEntitiesQueue();
14002
14003         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14004         for (i = 0;i < r_refdef.scene.numentities;i++)
14005                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14006
14007         r_refdef.stats.totaldecals += numdecals;
14008
14009         if (r_showsurfaces.integer)
14010                 return;
14011
14012         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14013
14014         for (i = 0;i < r_refdef.scene.numentities;i++)
14015         {
14016                 if (!r_refdef.viewcache.entityvisible[i])
14017                         continue;
14018                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14019                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14020         }
14021 }
14022
14023 extern cvar_t mod_collision_bih;
14024 void R_DrawDebugModel(void)
14025 {
14026         entity_render_t *ent = rsurface.entity;
14027         int i, j, k, l, flagsmask;
14028         const msurface_t *surface;
14029         dp_model_t *model = ent->model;
14030         vec3_t v;
14031
14032         switch(vid.renderpath)
14033         {
14034         case RENDERPATH_GL11:
14035         case RENDERPATH_GL13:
14036         case RENDERPATH_GL20:
14037         case RENDERPATH_CGGL:
14038                 break;
14039         case RENDERPATH_D3D9:
14040                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14041                 return;
14042         case RENDERPATH_D3D10:
14043                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14044                 return;
14045         case RENDERPATH_D3D11:
14046                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14047                 return;
14048         }
14049
14050         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14051
14052         R_Mesh_ResetTextureState();
14053         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14054         GL_DepthRange(0, 1);
14055         GL_DepthTest(!r_showdisabledepthtest.integer);
14056         GL_DepthMask(false);
14057         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14058
14059         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14060         {
14061                 int triangleindex;
14062                 int bihleafindex;
14063                 qboolean cullbox = ent == r_refdef.scene.worldentity;
14064                 const q3mbrush_t *brush;
14065                 const bih_t *bih = &model->collision_bih;
14066                 const bih_leaf_t *bihleaf;
14067                 float vertex3f[3][3];
14068                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14069                 cullbox = false;
14070                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14071                 {
14072                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14073                                 continue;
14074                         switch (bihleaf->type)
14075                         {
14076                         case BIH_BRUSH:
14077                                 brush = model->brush.data_brushes + bihleaf->itemindex;
14078                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
14079                                 {
14080                                         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);
14081                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14082                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14083                                 }
14084                                 break;
14085                         case BIH_COLLISIONTRIANGLE:
14086                                 triangleindex = bihleaf->itemindex;
14087                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14088                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14089                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14090                                 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);
14091                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14092                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14093                                 break;
14094                         case BIH_RENDERTRIANGLE:
14095                                 triangleindex = bihleaf->itemindex;
14096                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14097                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14098                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14099                                 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);
14100                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14101                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14102                                 break;
14103                         }
14104                 }
14105         }
14106
14107         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14108
14109         if (r_showtris.integer || r_shownormals.integer)
14110         {
14111                 if (r_showdisabledepthtest.integer)
14112                 {
14113                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14114                         GL_DepthMask(false);
14115                 }
14116                 else
14117                 {
14118                         GL_BlendFunc(GL_ONE, GL_ZERO);
14119                         GL_DepthMask(true);
14120                 }
14121                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14122                 {
14123                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14124                                 continue;
14125                         rsurface.texture = R_GetCurrentTexture(surface->texture);
14126                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14127                         {
14128                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14129                                 if (r_showtris.value > 0)
14130                                 {
14131                                         if (!rsurface.texture->currentlayers->depthmask)
14132                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14133                                         else if (ent == r_refdef.scene.worldentity)
14134                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14135                                         else
14136                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14137                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14138                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14139                                         RSurf_DrawBatch();
14140                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14141                                         CHECKGLERROR
14142                                 }
14143                                 if (r_shownormals.value < 0)
14144                                 {
14145                                         qglBegin(GL_LINES);
14146                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14147                                         {
14148                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14149                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14150                                                 qglVertex3f(v[0], v[1], v[2]);
14151                                                 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14152                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14153                                                 qglVertex3f(v[0], v[1], v[2]);
14154                                         }
14155                                         qglEnd();
14156                                         CHECKGLERROR
14157                                 }
14158                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14159                                 {
14160                                         qglBegin(GL_LINES);
14161                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14162                                         {
14163                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14164                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14165                                                 qglVertex3f(v[0], v[1], v[2]);
14166                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14167                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14168                                                 qglVertex3f(v[0], v[1], v[2]);
14169                                         }
14170                                         qglEnd();
14171                                         CHECKGLERROR
14172                                         qglBegin(GL_LINES);
14173                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14174                                         {
14175                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14176                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14177                                                 qglVertex3f(v[0], v[1], v[2]);
14178                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14179                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14180                                                 qglVertex3f(v[0], v[1], v[2]);
14181                                         }
14182                                         qglEnd();
14183                                         CHECKGLERROR
14184                                         qglBegin(GL_LINES);
14185                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14186                                         {
14187                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14188                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14189                                                 qglVertex3f(v[0], v[1], v[2]);
14190                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14191                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14192                                                 qglVertex3f(v[0], v[1], v[2]);
14193                                         }
14194                                         qglEnd();
14195                                         CHECKGLERROR
14196                                 }
14197                         }
14198                 }
14199                 rsurface.texture = NULL;
14200         }
14201 }
14202
14203 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14204 int r_maxsurfacelist = 0;
14205 const msurface_t **r_surfacelist = NULL;
14206 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14207 {
14208         int i, j, endj, flagsmask;
14209         dp_model_t *model = r_refdef.scene.worldmodel;
14210         msurface_t *surfaces;
14211         unsigned char *update;
14212         int numsurfacelist = 0;
14213         if (model == NULL)
14214                 return;
14215
14216         if (r_maxsurfacelist < model->num_surfaces)
14217         {
14218                 r_maxsurfacelist = model->num_surfaces;
14219                 if (r_surfacelist)
14220                         Mem_Free((msurface_t**)r_surfacelist);
14221                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14222         }
14223
14224         RSurf_ActiveWorldEntity();
14225
14226         surfaces = model->data_surfaces;
14227         update = model->brushq1.lightmapupdateflags;
14228
14229         // update light styles on this submodel
14230         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14231         {
14232                 model_brush_lightstyleinfo_t *style;
14233                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14234                 {
14235                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14236                         {
14237                                 int *list = style->surfacelist;
14238                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14239                                 for (j = 0;j < style->numsurfaces;j++)
14240                                         update[list[j]] = true;
14241                         }
14242                 }
14243         }
14244
14245         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14246
14247         if (debug)
14248         {
14249                 R_DrawDebugModel();
14250                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14251                 return;
14252         }
14253
14254         rsurface.lightmaptexture = NULL;
14255         rsurface.deluxemaptexture = NULL;
14256         rsurface.uselightmaptexture = false;
14257         rsurface.texture = NULL;
14258         rsurface.rtlight = NULL;
14259         numsurfacelist = 0;
14260         // add visible surfaces to draw list
14261         for (i = 0;i < model->nummodelsurfaces;i++)
14262         {
14263                 j = model->sortedmodelsurfaces[i];
14264                 if (r_refdef.viewcache.world_surfacevisible[j])
14265                         r_surfacelist[numsurfacelist++] = surfaces + j;
14266         }
14267         // update lightmaps if needed
14268         if (model->brushq1.firstrender)
14269         {
14270                 model->brushq1.firstrender = false;
14271                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14272                         if (update[j])
14273                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14274         }
14275         else if (update)
14276         {
14277                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14278                         if (r_refdef.viewcache.world_surfacevisible[j])
14279                                 if (update[j])
14280                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14281         }
14282         // don't do anything if there were no surfaces
14283         if (!numsurfacelist)
14284         {
14285                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14286                 return;
14287         }
14288         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14289         GL_AlphaTest(false);
14290
14291         // add to stats if desired
14292         if (r_speeds.integer && !skysurfaces && !depthonly)
14293         {
14294                 r_refdef.stats.world_surfaces += numsurfacelist;
14295                 for (j = 0;j < numsurfacelist;j++)
14296                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14297         }
14298
14299         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14300 }
14301
14302 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14303 {
14304         int i, j, endj, flagsmask;
14305         dp_model_t *model = ent->model;
14306         msurface_t *surfaces;
14307         unsigned char *update;
14308         int numsurfacelist = 0;
14309         if (model == NULL)
14310                 return;
14311
14312         if (r_maxsurfacelist < model->num_surfaces)
14313         {
14314                 r_maxsurfacelist = model->num_surfaces;
14315                 if (r_surfacelist)
14316                         Mem_Free((msurface_t **)r_surfacelist);
14317                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14318         }
14319
14320         // if the model is static it doesn't matter what value we give for
14321         // wantnormals and wanttangents, so this logic uses only rules applicable
14322         // to a model, knowing that they are meaningless otherwise
14323         if (ent == r_refdef.scene.worldentity)
14324                 RSurf_ActiveWorldEntity();
14325         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14326                 RSurf_ActiveModelEntity(ent, false, false, false);
14327         else if (prepass)
14328                 RSurf_ActiveModelEntity(ent, true, true, true);
14329         else if (depthonly)
14330         {
14331                 switch (vid.renderpath)
14332                 {
14333                 case RENDERPATH_GL20:
14334                 case RENDERPATH_CGGL:
14335                 case RENDERPATH_D3D9:
14336                 case RENDERPATH_D3D10:
14337                 case RENDERPATH_D3D11:
14338                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14339                         break;
14340                 case RENDERPATH_GL13:
14341                 case RENDERPATH_GL11:
14342                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14343                         break;
14344                 }
14345         }
14346         else
14347         {
14348                 switch (vid.renderpath)
14349                 {
14350                 case RENDERPATH_GL20:
14351                 case RENDERPATH_CGGL:
14352                 case RENDERPATH_D3D9:
14353                 case RENDERPATH_D3D10:
14354                 case RENDERPATH_D3D11:
14355                         RSurf_ActiveModelEntity(ent, true, true, false);
14356                         break;
14357                 case RENDERPATH_GL13:
14358                 case RENDERPATH_GL11:
14359                         RSurf_ActiveModelEntity(ent, true, false, false);
14360                         break;
14361                 }
14362         }
14363
14364         surfaces = model->data_surfaces;
14365         update = model->brushq1.lightmapupdateflags;
14366
14367         // update light styles
14368         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14369         {
14370                 model_brush_lightstyleinfo_t *style;
14371                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14372                 {
14373                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14374                         {
14375                                 int *list = style->surfacelist;
14376                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14377                                 for (j = 0;j < style->numsurfaces;j++)
14378                                         update[list[j]] = true;
14379                         }
14380                 }
14381         }
14382
14383         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14384
14385         if (debug)
14386         {
14387                 R_DrawDebugModel();
14388                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14389                 return;
14390         }
14391
14392         rsurface.lightmaptexture = NULL;
14393         rsurface.deluxemaptexture = NULL;
14394         rsurface.uselightmaptexture = false;
14395         rsurface.texture = NULL;
14396         rsurface.rtlight = NULL;
14397         numsurfacelist = 0;
14398         // add visible surfaces to draw list
14399         for (i = 0;i < model->nummodelsurfaces;i++)
14400                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14401         // don't do anything if there were no surfaces
14402         if (!numsurfacelist)
14403         {
14404                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14405                 return;
14406         }
14407         // update lightmaps if needed
14408         if (update)
14409         {
14410                 int updated = 0;
14411                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14412                 {
14413                         if (update[j])
14414                         {
14415                                 updated++;
14416                                 R_BuildLightMap(ent, surfaces + j);
14417                         }
14418                 }
14419         }
14420         if (update)
14421                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14422                         if (update[j])
14423                                 R_BuildLightMap(ent, surfaces + j);
14424         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14425         GL_AlphaTest(false);
14426
14427         // add to stats if desired
14428         if (r_speeds.integer && !skysurfaces && !depthonly)
14429         {
14430                 r_refdef.stats.entities_surfaces += numsurfacelist;
14431                 for (j = 0;j < numsurfacelist;j++)
14432                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14433         }
14434
14435         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14436 }
14437
14438 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14439 {
14440         static texture_t texture;
14441         static msurface_t surface;
14442         const msurface_t *surfacelist = &surface;
14443
14444         // fake enough texture and surface state to render this geometry
14445
14446         texture.update_lastrenderframe = -1; // regenerate this texture
14447         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14448         texture.currentskinframe = skinframe;
14449         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14450         texture.offsetmapping = OFFSETMAPPING_OFF;
14451         texture.offsetscale = 1;
14452         texture.specularscalemod = 1;
14453         texture.specularpowermod = 1;
14454
14455         surface.texture = &texture;
14456         surface.num_triangles = numtriangles;
14457         surface.num_firsttriangle = firsttriangle;
14458         surface.num_vertices = numvertices;
14459         surface.num_firstvertex = firstvertex;
14460
14461         // now render it
14462         rsurface.texture = R_GetCurrentTexture(surface.texture);
14463         rsurface.lightmaptexture = NULL;
14464         rsurface.deluxemaptexture = NULL;
14465         rsurface.uselightmaptexture = false;
14466         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14467 }
14468
14469 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)
14470 {
14471         static msurface_t surface;
14472         const msurface_t *surfacelist = &surface;
14473
14474         // fake enough texture and surface state to render this geometry
14475
14476         surface.texture = texture;
14477         surface.num_triangles = numtriangles;
14478         surface.num_firsttriangle = firsttriangle;
14479         surface.num_vertices = numvertices;
14480         surface.num_firstvertex = firstvertex;
14481
14482         // now render it
14483         rsurface.texture = R_GetCurrentTexture(surface.texture);
14484         rsurface.lightmaptexture = NULL;
14485         rsurface.deluxemaptexture = NULL;
14486         rsurface.uselightmaptexture = false;
14487         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14488 }