]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
fix a stupid extra declaration in the glsl shader
[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 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
152 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
153 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
154 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
155
156 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)"};
157 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
158 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"};
159 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
160 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
161 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
162
163 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
164 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
165 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
166 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
167
168 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
169 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
170 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
171 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
172 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
173 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
174 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
175
176 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
177 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
178 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
179 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)"};
180
181 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"};
182
183 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"};
184
185 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
186
187 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
188 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"};
189 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
190 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
191 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
192 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
193 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)"};
194
195 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
196 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"};
197
198 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)"};
199
200 extern cvar_t v_glslgamma;
201
202 extern qboolean v_flipped_state;
203
204 static struct r_bloomstate_s
205 {
206         qboolean enabled;
207         qboolean hdr;
208
209         int bloomwidth, bloomheight;
210
211         int screentexturewidth, screentextureheight;
212         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
213
214         int bloomtexturewidth, bloomtextureheight;
215         rtexture_t *texture_bloom;
216
217         // arrays for rendering the screen passes
218         float screentexcoord2f[8];
219         float bloomtexcoord2f[8];
220         float offsettexcoord2f[8];
221
222         r_viewport_t viewport;
223 }
224 r_bloomstate;
225
226 r_waterstate_t r_waterstate;
227
228 /// shadow volume bsp struct with automatically growing nodes buffer
229 svbsp_t r_svbsp;
230
231 rtexture_t *r_texture_blanknormalmap;
232 rtexture_t *r_texture_white;
233 rtexture_t *r_texture_grey128;
234 rtexture_t *r_texture_black;
235 rtexture_t *r_texture_notexture;
236 rtexture_t *r_texture_whitecube;
237 rtexture_t *r_texture_normalizationcube;
238 rtexture_t *r_texture_fogattenuation;
239 rtexture_t *r_texture_fogheighttexture;
240 rtexture_t *r_texture_gammaramps;
241 unsigned int r_texture_gammaramps_serial;
242 //rtexture_t *r_texture_fogintensity;
243 rtexture_t *r_texture_reflectcube;
244
245 // TODO: hash lookups?
246 typedef struct cubemapinfo_s
247 {
248         char basename[64];
249         rtexture_t *texture;
250 }
251 cubemapinfo_t;
252
253 int r_texture_numcubemaps;
254 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
255
256 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
257 unsigned int r_numqueries;
258 unsigned int r_maxqueries;
259
260 typedef struct r_qwskincache_s
261 {
262         char name[MAX_QPATH];
263         skinframe_t *skinframe;
264 }
265 r_qwskincache_t;
266
267 static r_qwskincache_t *r_qwskincache;
268 static int r_qwskincache_size;
269
270 /// vertex coordinates for a quad that covers the screen exactly
271 extern const float r_screenvertex3f[12];
272 extern const float r_d3dscreenvertex3f[12];
273 const float r_screenvertex3f[12] =
274 {
275         0, 0, 0,
276         1, 0, 0,
277         1, 1, 0,
278         0, 1, 0
279 };
280 const float r_d3dscreenvertex3f[12] =
281 {
282         0, 1, 0,
283         1, 1, 0,
284         1, 0, 0,
285         0, 0, 0
286 };
287
288 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
289 {
290         int i;
291         for (i = 0;i < verts;i++)
292         {
293                 out[0] = in[0] * r;
294                 out[1] = in[1] * g;
295                 out[2] = in[2] * b;
296                 out[3] = in[3];
297                 in += 4;
298                 out += 4;
299         }
300 }
301
302 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
303 {
304         int i;
305         for (i = 0;i < verts;i++)
306         {
307                 out[0] = r;
308                 out[1] = g;
309                 out[2] = b;
310                 out[3] = a;
311                 out += 4;
312         }
313 }
314
315 // FIXME: move this to client?
316 void FOG_clear(void)
317 {
318         if (gamemode == GAME_NEHAHRA)
319         {
320                 Cvar_Set("gl_fogenable", "0");
321                 Cvar_Set("gl_fogdensity", "0.2");
322                 Cvar_Set("gl_fogred", "0.3");
323                 Cvar_Set("gl_foggreen", "0.3");
324                 Cvar_Set("gl_fogblue", "0.3");
325         }
326         r_refdef.fog_density = 0;
327         r_refdef.fog_red = 0;
328         r_refdef.fog_green = 0;
329         r_refdef.fog_blue = 0;
330         r_refdef.fog_alpha = 1;
331         r_refdef.fog_start = 0;
332         r_refdef.fog_end = 16384;
333         r_refdef.fog_height = 1<<30;
334         r_refdef.fog_fadedepth = 128;
335         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
336 }
337
338 static void R_BuildBlankTextures(void)
339 {
340         unsigned char data[4];
341         data[2] = 128; // normal X
342         data[1] = 128; // normal Y
343         data[0] = 255; // normal Z
344         data[3] = 128; // height
345         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
346         data[0] = 255;
347         data[1] = 255;
348         data[2] = 255;
349         data[3] = 255;
350         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
351         data[0] = 128;
352         data[1] = 128;
353         data[2] = 128;
354         data[3] = 255;
355         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
356         data[0] = 0;
357         data[1] = 0;
358         data[2] = 0;
359         data[3] = 255;
360         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
361 }
362
363 static void R_BuildNoTexture(void)
364 {
365         int x, y;
366         unsigned char pix[16][16][4];
367         // this makes a light grey/dark grey checkerboard texture
368         for (y = 0;y < 16;y++)
369         {
370                 for (x = 0;x < 16;x++)
371                 {
372                         if ((y < 8) ^ (x < 8))
373                         {
374                                 pix[y][x][0] = 128;
375                                 pix[y][x][1] = 128;
376                                 pix[y][x][2] = 128;
377                                 pix[y][x][3] = 255;
378                         }
379                         else
380                         {
381                                 pix[y][x][0] = 64;
382                                 pix[y][x][1] = 64;
383                                 pix[y][x][2] = 64;
384                                 pix[y][x][3] = 255;
385                         }
386                 }
387         }
388         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
389 }
390
391 static void R_BuildWhiteCube(void)
392 {
393         unsigned char data[6*1*1*4];
394         memset(data, 255, sizeof(data));
395         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
396 }
397
398 static void R_BuildNormalizationCube(void)
399 {
400         int x, y, side;
401         vec3_t v;
402         vec_t s, t, intensity;
403 #define NORMSIZE 64
404         unsigned char *data;
405         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
406         for (side = 0;side < 6;side++)
407         {
408                 for (y = 0;y < NORMSIZE;y++)
409                 {
410                         for (x = 0;x < NORMSIZE;x++)
411                         {
412                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
413                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
414                                 switch(side)
415                                 {
416                                 default:
417                                 case 0:
418                                         v[0] = 1;
419                                         v[1] = -t;
420                                         v[2] = -s;
421                                         break;
422                                 case 1:
423                                         v[0] = -1;
424                                         v[1] = -t;
425                                         v[2] = s;
426                                         break;
427                                 case 2:
428                                         v[0] = s;
429                                         v[1] = 1;
430                                         v[2] = t;
431                                         break;
432                                 case 3:
433                                         v[0] = s;
434                                         v[1] = -1;
435                                         v[2] = -t;
436                                         break;
437                                 case 4:
438                                         v[0] = s;
439                                         v[1] = -t;
440                                         v[2] = 1;
441                                         break;
442                                 case 5:
443                                         v[0] = -s;
444                                         v[1] = -t;
445                                         v[2] = -1;
446                                         break;
447                                 }
448                                 intensity = 127.0f / sqrt(DotProduct(v, v));
449                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
450                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
451                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
452                                 data[((side*64+y)*64+x)*4+3] = 255;
453                         }
454                 }
455         }
456         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
457         Mem_Free(data);
458 }
459
460 static void R_BuildFogTexture(void)
461 {
462         int x, b;
463 #define FOGWIDTH 256
464         unsigned char data1[FOGWIDTH][4];
465         //unsigned char data2[FOGWIDTH][4];
466         double d, r, alpha;
467
468         r_refdef.fogmasktable_start = r_refdef.fog_start;
469         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
470         r_refdef.fogmasktable_range = r_refdef.fogrange;
471         r_refdef.fogmasktable_density = r_refdef.fog_density;
472
473         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
474         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
475         {
476                 d = (x * r - r_refdef.fogmasktable_start);
477                 if(developer_extra.integer)
478                         Con_DPrintf("%f ", d);
479                 d = max(0, d);
480                 if (r_fog_exp2.integer)
481                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
482                 else
483                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
484                 if(developer_extra.integer)
485                         Con_DPrintf(" : %f ", alpha);
486                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
487                 if(developer_extra.integer)
488                         Con_DPrintf(" = %f\n", alpha);
489                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
490         }
491
492         for (x = 0;x < FOGWIDTH;x++)
493         {
494                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
495                 data1[x][0] = b;
496                 data1[x][1] = b;
497                 data1[x][2] = b;
498                 data1[x][3] = 255;
499                 //data2[x][0] = 255 - b;
500                 //data2[x][1] = 255 - b;
501                 //data2[x][2] = 255 - b;
502                 //data2[x][3] = 255;
503         }
504         if (r_texture_fogattenuation)
505         {
506                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
507                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
508         }
509         else
510         {
511                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
512                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
513         }
514 }
515
516 static void R_BuildFogHeightTexture(void)
517 {
518         unsigned char *inpixels;
519         int size;
520         int x;
521         int y;
522         int j;
523         float c[4];
524         float f;
525         inpixels = NULL;
526         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
527         if (r_refdef.fogheighttexturename[0])
528                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
529         if (!inpixels)
530         {
531                 r_refdef.fog_height_tablesize = 0;
532                 if (r_texture_fogheighttexture)
533                         R_FreeTexture(r_texture_fogheighttexture);
534                 r_texture_fogheighttexture = NULL;
535                 if (r_refdef.fog_height_table2d)
536                         Mem_Free(r_refdef.fog_height_table2d);
537                 r_refdef.fog_height_table2d = NULL;
538                 if (r_refdef.fog_height_table1d)
539                         Mem_Free(r_refdef.fog_height_table1d);
540                 r_refdef.fog_height_table1d = NULL;
541                 return;
542         }
543         size = image_width;
544         r_refdef.fog_height_tablesize = size;
545         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
546         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
547         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
548         Mem_Free(inpixels);
549         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
550         // average fog color table accounting for every fog layer between a point
551         // and the camera.  (Note: attenuation is handled separately!)
552         for (y = 0;y < size;y++)
553         {
554                 for (x = 0;x < size;x++)
555                 {
556                         Vector4Clear(c);
557                         f = 0;
558                         if (x < y)
559                         {
560                                 for (j = x;j <= y;j++)
561                                 {
562                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
563                                         f++;
564                                 }
565                         }
566                         else
567                         {
568                                 for (j = x;j >= y;j--)
569                                 {
570                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
571                                         f++;
572                                 }
573                         }
574                         f = 1.0f / f;
575                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
576                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
577                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
578                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
579                 }
580         }
581         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
582 }
583
584 //=======================================================================================================================================================
585
586 static const char *builtinshaderstring =
587 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
588 "// written by Forest 'LordHavoc' Hale\n"
589 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
590 "\n"
591 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
592 "# define USEFOG\n"
593 "#endif\n"
594 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
595 "#define USELIGHTMAP\n"
596 "#endif\n"
597 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
598 "#define USEEYEVECTOR\n"
599 "#endif\n"
600 "\n"
601 "#ifdef USESHADOWMAP2D\n"
602 "# ifdef GL_EXT_gpu_shader4\n"
603 "#   extension GL_EXT_gpu_shader4 : enable\n"
604 "# endif\n"
605 "# ifdef GL_ARB_texture_gather\n"
606 "#   extension GL_ARB_texture_gather : enable\n"
607 "# else\n"
608 "#   ifdef GL_AMD_texture_texture4\n"
609 "#     extension GL_AMD_texture_texture4 : enable\n"
610 "#   endif\n"
611 "# endif\n"
612 "#endif\n"
613 "\n"
614 "//#ifdef USESHADOWSAMPLER\n"
615 "//# extension GL_ARB_shadow : enable\n"
616 "//#endif\n"
617 "\n"
618 "//#ifdef __GLSL_CG_DATA_TYPES\n"
619 "//# define myhalf half\n"
620 "//# define myhalf2 half2\n"
621 "//# define myhalf3 half3\n"
622 "//# define myhalf4 half4\n"
623 "//#else\n"
624 "# define myhalf float\n"
625 "# define myhalf2 vec2\n"
626 "# define myhalf3 vec3\n"
627 "# define myhalf4 vec4\n"
628 "//#endif\n"
629 "\n"
630 "#ifdef VERTEX_SHADER\n"
631 "uniform mat4 ModelViewProjectionMatrix;\n"
632 "#endif\n"
633 "\n"
634 "#ifdef MODE_DEPTH_OR_SHADOW\n"
635 "#ifdef VERTEX_SHADER\n"
636 "void main(void)\n"
637 "{\n"
638 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
639 "}\n"
640 "#endif\n"
641 "#else // !MODE_DEPTH_ORSHADOW\n"
642 "\n"
643 "\n"
644 "\n"
645 "\n"
646 "#ifdef MODE_SHOWDEPTH\n"
647 "#ifdef VERTEX_SHADER\n"
648 "void main(void)\n"
649 "{\n"
650 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
651 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
652 "}\n"
653 "#endif\n"
654 "\n"
655 "#ifdef FRAGMENT_SHADER\n"
656 "void main(void)\n"
657 "{\n"
658 "       gl_FragColor = gl_Color;\n"
659 "}\n"
660 "#endif\n"
661 "#else // !MODE_SHOWDEPTH\n"
662 "\n"
663 "\n"
664 "\n"
665 "\n"
666 "#ifdef MODE_POSTPROCESS\n"
667 "varying vec2 TexCoord1;\n"
668 "varying vec2 TexCoord2;\n"
669 "\n"
670 "#ifdef VERTEX_SHADER\n"
671 "void main(void)\n"
672 "{\n"
673 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
674 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
675 "#ifdef USEBLOOM\n"
676 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
677 "#endif\n"
678 "}\n"
679 "#endif\n"
680 "\n"
681 "#ifdef FRAGMENT_SHADER\n"
682 "uniform sampler2D Texture_First;\n"
683 "#ifdef USEBLOOM\n"
684 "uniform sampler2D Texture_Second;\n"
685 "uniform vec4 BloomColorSubtract;\n"
686 "#endif\n"
687 "#ifdef USEGAMMARAMPS\n"
688 "uniform sampler2D Texture_GammaRamps;\n"
689 "#endif\n"
690 "#ifdef USESATURATION\n"
691 "uniform float Saturation;\n"
692 "#endif\n"
693 "#ifdef USEVIEWTINT\n"
694 "uniform vec4 ViewTintColor;\n"
695 "#endif\n"
696 "//uncomment these if you want to use them:\n"
697 "uniform vec4 UserVec1;\n"
698 "uniform vec4 UserVec2;\n"
699 "// uniform vec4 UserVec3;\n"
700 "// uniform vec4 UserVec4;\n"
701 "// uniform float ClientTime;\n"
702 "uniform vec2 PixelSize;\n"
703 "void main(void)\n"
704 "{\n"
705 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
706 "#ifdef USEBLOOM\n"
707 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
708 "#endif\n"
709 "#ifdef USEVIEWTINT\n"
710 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
711 "#endif\n"
712 "\n"
713 "#ifdef USEPOSTPROCESSING\n"
714 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
715 "// 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"
716 "       float sobel = 1.0;\n"
717 "       // vec2 ts = textureSize(Texture_First, 0);\n"
718 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
719 "       vec2 px = PixelSize;\n"
720 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
721 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
722 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
723 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
724 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
725 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
726 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
727 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
728 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
729 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
730 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
731 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
732 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
733 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
734 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
735 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
736 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
737 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
738 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
739 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
740 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
741 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
742 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
743 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
744 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
745 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
746 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
747 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
748 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
749 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
750 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
751 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
752 "#endif\n"
753 "\n"
754 "#ifdef USESATURATION\n"
755 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
756 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
757 "       // 'vampire sight' effect, wheres red is compensated\n"
758 "       #ifdef SATURATION_REDCOMPENSATE\n"
759 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
760 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
761 "               gl_FragColor.r += rboost;\n"
762 "       #else\n"
763 "               // normal desaturation\n"
764 "               //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
765 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
766 "       #endif\n"
767 "#endif\n"
768 "\n"
769 "#ifdef USEGAMMARAMPS\n"
770 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
771 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
772 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
773 "#endif\n"
774 "}\n"
775 "#endif\n"
776 "#else // !MODE_POSTPROCESS\n"
777 "\n"
778 "\n"
779 "\n"
780 "\n"
781 "#ifdef MODE_GENERIC\n"
782 "#ifdef USEDIFFUSE\n"
783 "varying vec2 TexCoord1;\n"
784 "#endif\n"
785 "#ifdef USESPECULAR\n"
786 "varying vec2 TexCoord2;\n"
787 "#endif\n"
788 "#ifdef VERTEX_SHADER\n"
789 "void main(void)\n"
790 "{\n"
791 "       gl_FrontColor = gl_Color;\n"
792 "#ifdef USEDIFFUSE\n"
793 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
794 "#endif\n"
795 "#ifdef USESPECULAR\n"
796 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
797 "#endif\n"
798 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
799 "}\n"
800 "#endif\n"
801 "\n"
802 "#ifdef FRAGMENT_SHADER\n"
803 "#ifdef USEDIFFUSE\n"
804 "uniform sampler2D Texture_First;\n"
805 "#endif\n"
806 "#ifdef USESPECULAR\n"
807 "uniform sampler2D Texture_Second;\n"
808 "#endif\n"
809 "\n"
810 "void main(void)\n"
811 "{\n"
812 "#ifdef USEVIEWTINT\n"
813 "       gl_FragColor = gl_Color;\n"
814 "#else\n"
815 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
816 "#endif\n"
817 "#ifdef USEDIFFUSE\n"
818 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
819 "#endif\n"
820 "\n"
821 "#ifdef USESPECULAR\n"
822 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
823 "# ifdef USECOLORMAPPING\n"
824 "       gl_FragColor *= tex2;\n"
825 "# endif\n"
826 "# ifdef USEGLOW\n"
827 "       gl_FragColor += tex2;\n"
828 "# endif\n"
829 "# ifdef USEVERTEXTEXTUREBLEND\n"
830 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
831 "# endif\n"
832 "#endif\n"
833 "}\n"
834 "#endif\n"
835 "#else // !MODE_GENERIC\n"
836 "\n"
837 "\n"
838 "\n"
839 "\n"
840 "#ifdef MODE_BLOOMBLUR\n"
841 "varying TexCoord;\n"
842 "#ifdef VERTEX_SHADER\n"
843 "void main(void)\n"
844 "{\n"
845 "       gl_FrontColor = gl_Color;\n"
846 "       TexCoord = gl_MultiTexCoord0.xy;\n"
847 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
848 "}\n"
849 "#endif\n"
850 "\n"
851 "#ifdef FRAGMENT_SHADER\n"
852 "uniform sampler2D Texture_First;\n"
853 "uniform vec4 BloomBlur_Parameters;\n"
854 "\n"
855 "void main(void)\n"
856 "{\n"
857 "       int i;\n"
858 "       vec2 tc = TexCoord;\n"
859 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
860 "       tc += BloomBlur_Parameters.xy;\n"
861 "       for (i = 1;i < SAMPLES;i++)\n"
862 "       {\n"
863 "               color += texture2D(Texture_First, tc).rgb;\n"
864 "               tc += BloomBlur_Parameters.xy;\n"
865 "       }\n"
866 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
867 "}\n"
868 "#endif\n"
869 "#else // !MODE_BLOOMBLUR\n"
870 "#ifdef MODE_REFRACTION\n"
871 "varying vec2 TexCoord;\n"
872 "varying vec4 ModelViewProjectionPosition;\n"
873 "uniform mat4 TexMatrix;\n"
874 "#ifdef VERTEX_SHADER\n"
875 "\n"
876 "void main(void)\n"
877 "{\n"
878 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
879 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
880 "       ModelViewProjectionPosition = gl_Position;\n"
881 "}\n"
882 "#endif\n"
883 "\n"
884 "#ifdef FRAGMENT_SHADER\n"
885 "uniform sampler2D Texture_Normal;\n"
886 "uniform sampler2D Texture_Refraction;\n"
887 "uniform sampler2D Texture_Reflection;\n"
888 "\n"
889 "uniform vec4 DistortScaleRefractReflect;\n"
890 "uniform vec4 ScreenScaleRefractReflect;\n"
891 "uniform vec4 ScreenCenterRefractReflect;\n"
892 "uniform vec4 RefractColor;\n"
893 "uniform vec4 ReflectColor;\n"
894 "uniform float ReflectFactor;\n"
895 "uniform float ReflectOffset;\n"
896 "\n"
897 "void main(void)\n"
898 "{\n"
899 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
900 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
901 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
902 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
903 "       // FIXME temporary hack to detect the case that the reflection\n"
904 "       // gets blackened at edges due to leaving the area that contains actual\n"
905 "       // content.\n"
906 "       // Remove this 'ack once we have a better way to stop this thing from\n"
907 "       // 'appening.\n"
908 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
909 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
910 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
911 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
912 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
913 "       gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
914 "}\n"
915 "#endif\n"
916 "#else // !MODE_REFRACTION\n"
917 "\n"
918 "\n"
919 "\n"
920 "\n"
921 "#ifdef MODE_WATER\n"
922 "varying vec2 TexCoord;\n"
923 "varying vec3 EyeVector;\n"
924 "varying vec4 ModelViewProjectionPosition;\n"
925 "#ifdef VERTEX_SHADER\n"
926 "uniform vec3 EyePosition;\n"
927 "uniform mat4 TexMatrix;\n"
928 "\n"
929 "void main(void)\n"
930 "{\n"
931 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
932 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
933 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
934 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
935 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
936 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
937 "       ModelViewProjectionPosition = gl_Position;\n"
938 "}\n"
939 "#endif\n"
940 "\n"
941 "#ifdef FRAGMENT_SHADER\n"
942 "uniform sampler2D Texture_Normal;\n"
943 "uniform sampler2D Texture_Refraction;\n"
944 "uniform sampler2D Texture_Reflection;\n"
945 "\n"
946 "uniform vec4 DistortScaleRefractReflect;\n"
947 "uniform vec4 ScreenScaleRefractReflect;\n"
948 "uniform vec4 ScreenCenterRefractReflect;\n"
949 "uniform vec4 RefractColor;\n"
950 "uniform vec4 ReflectColor;\n"
951 "uniform float ReflectFactor;\n"
952 "uniform float ReflectOffset;\n"
953 "uniform float ClientTime;\n"
954 "#ifdef USENORMALMAPSCROLLBLEND\n"
955 "uniform vec2 NormalmapScrollBlend;\n"
956 "#endif\n"
957 "\n"
958 "void main(void)\n"
959 "{\n"
960 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
961 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
962 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
963 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
964 "       // slight water animation via 2 layer scrolling (todo: tweak)\n"
965 "       #ifdef USENORMALMAPSCROLLBLEND\n"
966 "               vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
967 "               normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
968 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
969 "       #else\n"
970 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
971 "       #endif\n"
972 "       // FIXME temporary hack to detect the case that the reflection\n"
973 "       // gets blackened at edges due to leaving the area that contains actual\n"
974 "       // content.\n"
975 "       // Remove this 'ack once we have a better way to stop this thing from\n"
976 "       // 'appening.\n"
977 "       float f  = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
978 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
979 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
980 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
981 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
982 "       f  = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
983 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
984 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
985 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
986 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
987 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
988 "       gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
989 "}\n"
990 "#endif\n"
991 "#else // !MODE_WATER\n"
992 "\n"
993 "\n"
994 "\n"
995 "\n"
996 "// common definitions between vertex shader and fragment shader:\n"
997 "\n"
998 "varying vec2 TexCoord;\n"
999 "#ifdef USEVERTEXTEXTUREBLEND\n"
1000 "varying vec2 TexCoord2;\n"
1001 "#endif\n"
1002 "#ifdef USELIGHTMAP\n"
1003 "varying vec2 TexCoordLightmap;\n"
1004 "#endif\n"
1005 "\n"
1006 "#ifdef MODE_LIGHTSOURCE\n"
1007 "varying vec3 CubeVector;\n"
1008 "#endif\n"
1009 "\n"
1010 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1011 "varying vec3 LightVector;\n"
1012 "#endif\n"
1013 "\n"
1014 "#ifdef USEEYEVECTOR\n"
1015 "varying vec3 EyeVector;\n"
1016 "#endif\n"
1017 "#ifdef USEFOG\n"
1018 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1019 "#endif\n"
1020 "\n"
1021 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1022 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1023 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1024 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
1025 "#endif\n"
1026 "\n"
1027 "#ifdef USEREFLECTION\n"
1028 "varying vec4 ModelViewProjectionPosition;\n"
1029 "#endif\n"
1030 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1031 "uniform vec3 LightPosition;\n"
1032 "varying vec4 ModelViewPosition;\n"
1033 "#endif\n"
1034 "\n"
1035 "#ifdef MODE_LIGHTSOURCE\n"
1036 "uniform vec3 LightPosition;\n"
1037 "#endif\n"
1038 "uniform vec3 EyePosition;\n"
1039 "#ifdef MODE_LIGHTDIRECTION\n"
1040 "uniform vec3 LightDir;\n"
1041 "#endif\n"
1042 "uniform vec4 FogPlane;\n"
1043 "\n"
1044 "#ifdef USESHADOWMAPORTHO\n"
1045 "varying vec3 ShadowMapTC;\n"
1046 "#endif\n"
1047 "\n"
1048 "\n"
1049 "\n"
1050 "\n"
1051 "\n"
1052 "// 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"
1053 "\n"
1054 "// fragment shader specific:\n"
1055 "#ifdef FRAGMENT_SHADER\n"
1056 "\n"
1057 "uniform sampler2D Texture_Normal;\n"
1058 "uniform sampler2D Texture_Color;\n"
1059 "uniform sampler2D Texture_Gloss;\n"
1060 "#ifdef USEGLOW\n"
1061 "uniform sampler2D Texture_Glow;\n"
1062 "#endif\n"
1063 "#ifdef USEVERTEXTEXTUREBLEND\n"
1064 "uniform sampler2D Texture_SecondaryNormal;\n"
1065 "uniform sampler2D Texture_SecondaryColor;\n"
1066 "uniform sampler2D Texture_SecondaryGloss;\n"
1067 "#ifdef USEGLOW\n"
1068 "uniform sampler2D Texture_SecondaryGlow;\n"
1069 "#endif\n"
1070 "#endif\n"
1071 "#ifdef USECOLORMAPPING\n"
1072 "uniform sampler2D Texture_Pants;\n"
1073 "uniform sampler2D Texture_Shirt;\n"
1074 "#endif\n"
1075 "#ifdef USEFOG\n"
1076 "#ifdef USEFOGHEIGHTTEXTURE\n"
1077 "uniform sampler2D Texture_FogHeightTexture;\n"
1078 "#endif\n"
1079 "uniform sampler2D Texture_FogMask;\n"
1080 "#endif\n"
1081 "#ifdef USELIGHTMAP\n"
1082 "uniform sampler2D Texture_Lightmap;\n"
1083 "#endif\n"
1084 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1085 "uniform sampler2D Texture_Deluxemap;\n"
1086 "#endif\n"
1087 "#ifdef USEREFLECTION\n"
1088 "uniform sampler2D Texture_Reflection;\n"
1089 "#endif\n"
1090 "\n"
1091 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1092 "uniform sampler2D Texture_ScreenDepth;\n"
1093 "uniform sampler2D Texture_ScreenNormalMap;\n"
1094 "#endif\n"
1095 "#ifdef USEDEFERREDLIGHTMAP\n"
1096 "uniform sampler2D Texture_ScreenDiffuse;\n"
1097 "uniform sampler2D Texture_ScreenSpecular;\n"
1098 "#endif\n"
1099 "\n"
1100 "uniform myhalf3 Color_Pants;\n"
1101 "uniform myhalf3 Color_Shirt;\n"
1102 "uniform myhalf3 FogColor;\n"
1103 "\n"
1104 "#ifdef USEFOG\n"
1105 "uniform float FogRangeRecip;\n"
1106 "uniform float FogPlaneViewDist;\n"
1107 "uniform float FogHeightFade;\n"
1108 "vec3 FogVertex(vec3 surfacecolor)\n"
1109 "{\n"
1110 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1111 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1112 "       float fogfrac;\n"
1113 "#ifdef USEFOGHEIGHTTEXTURE\n"
1114 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1115 "       fogfrac = fogheightpixel.a;\n"
1116 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1117 "#else\n"
1118 "# ifdef USEFOGOUTSIDE\n"
1119 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1120 "# else\n"
1121 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1122 "# endif\n"
1123 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1124 "#endif\n"
1125 "}\n"
1126 "#endif\n"
1127 "\n"
1128 "#ifdef USEOFFSETMAPPING\n"
1129 "uniform float OffsetMapping_Scale;\n"
1130 "vec2 OffsetMapping(vec2 TexCoord)\n"
1131 "{\n"
1132 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1133 "       // 14 sample relief mapping: linear search and then binary search\n"
1134 "       // this basically steps forward a small amount repeatedly until it finds\n"
1135 "       // itself inside solid, then jitters forward and back using decreasing\n"
1136 "       // amounts to find the impact\n"
1137 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1138 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1139 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1140 "       vec3 RT = vec3(TexCoord, 1);\n"
1141 "       OffsetVector *= 0.1;\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);\n"
1145 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1146 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1147 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1148 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1149 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1150 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1151 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1152 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1153 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1154 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1155 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1156 "       return RT.xy;\n"
1157 "#else\n"
1158 "       // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1159 "       // this basically moves forward the full distance, and then backs up based\n"
1160 "       // on height of samples\n"
1161 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1162 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1163 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1164 "       TexCoord += OffsetVector;\n"
1165 "       OffsetVector *= 0.5;\n"
1166 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1167 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1168 "       return TexCoord;\n"
1169 "#endif\n"
1170 "}\n"
1171 "#endif // USEOFFSETMAPPING\n"
1172 "\n"
1173 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1174 "uniform sampler2D Texture_Attenuation;\n"
1175 "uniform samplerCube Texture_Cube;\n"
1176 "#endif\n"
1177 "\n"
1178 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1179 "\n"
1180 "#ifdef USESHADOWMAP2D\n"
1181 "# ifdef USESHADOWSAMPLER\n"
1182 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1183 "# else\n"
1184 "uniform sampler2D Texture_ShadowMap2D;\n"
1185 "# endif\n"
1186 "#endif\n"
1187 "\n"
1188 "#ifdef USESHADOWMAPVSDCT\n"
1189 "uniform samplerCube Texture_CubeProjection;\n"
1190 "#endif\n"
1191 "\n"
1192 "#if defined(USESHADOWMAP2D)\n"
1193 "uniform vec2 ShadowMap_TextureScale;\n"
1194 "uniform vec4 ShadowMap_Parameters;\n"
1195 "#endif\n"
1196 "\n"
1197 "#if defined(USESHADOWMAP2D)\n"
1198 "# ifdef USESHADOWMAPORTHO\n"
1199 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1200 "# else\n"
1201 "#  ifdef USESHADOWMAPVSDCT\n"
1202 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1203 "{\n"
1204 "       vec3 adir = abs(dir);\n"
1205 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1206 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1207 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1208 "}\n"
1209 "#  else\n"
1210 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1211 "{\n"
1212 "       vec3 adir = abs(dir);\n"
1213 "       float ma = adir.z;\n"
1214 "       vec4 proj = vec4(dir, 2.5);\n"
1215 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1216 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1217 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1218 "       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"
1219 "}\n"
1220 "#  endif\n"
1221 "# endif\n"
1222 "#endif // defined(USESHADOWMAP2D)\n"
1223 "\n"
1224 "# ifdef USESHADOWMAP2D\n"
1225 "float ShadowMapCompare(vec3 dir)\n"
1226 "{\n"
1227 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1228 "       float f;\n"
1229 "\n"
1230 "#  ifdef USESHADOWSAMPLER\n"
1231 "#    ifdef USESHADOWMAPPCF\n"
1232 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1233 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1234 "       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"
1235 "#    else\n"
1236 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1237 "#    endif\n"
1238 "#  else\n"
1239 "#    ifdef USESHADOWMAPPCF\n"
1240 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1241 "#      ifdef GL_ARB_texture_gather\n"
1242 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1243 "#      else\n"
1244 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1245 "#      endif\n"
1246 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1247 "#      if USESHADOWMAPPCF > 1\n"
1248 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1249 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1250 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1251 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1252 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1253 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1254 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1255 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1256 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1257 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1258 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1259 "       locols.yz += group2.ab;\n"
1260 "       hicols.yz += group8.rg;\n"
1261 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1262 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1263 "                               mix(locols, hicols, offset.y);\n"
1264 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1265 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1266 "       f = dot(cols, vec4(1.0/25.0));\n"
1267 "#      else\n"
1268 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1269 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1270 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1271 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1272 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1273 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1274 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1275 "#      endif\n"
1276 "#     else\n"
1277 "#      ifdef GL_EXT_gpu_shader4\n"
1278 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1279 "#      else\n"
1280 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1281 "#      endif\n"
1282 "#      if USESHADOWMAPPCF > 1\n"
1283 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1284 "       center *= ShadowMap_TextureScale;\n"
1285 "       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"
1286 "       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"
1287 "       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"
1288 "       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"
1289 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1290 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1291 "#      else\n"
1292 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1293 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1294 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1295 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1296 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1297 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1298 "#      endif\n"
1299 "#     endif\n"
1300 "#    else\n"
1301 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1302 "#    endif\n"
1303 "#  endif\n"
1304 "#  ifdef USESHADOWMAPORTHO\n"
1305 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1306 "#  else\n"
1307 "       return f;\n"
1308 "#  endif\n"
1309 "}\n"
1310 "# endif\n"
1311 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1312 "#endif // FRAGMENT_SHADER\n"
1313 "\n"
1314 "\n"
1315 "\n"
1316 "\n"
1317 "#ifdef MODE_DEFERREDGEOMETRY\n"
1318 "#ifdef VERTEX_SHADER\n"
1319 "uniform mat4 TexMatrix;\n"
1320 "#ifdef USEVERTEXTEXTUREBLEND\n"
1321 "uniform mat4 BackgroundTexMatrix;\n"
1322 "#endif\n"
1323 "uniform mat4 ModelViewMatrix;\n"
1324 "void main(void)\n"
1325 "{\n"
1326 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1327 "#ifdef USEVERTEXTEXTUREBLEND\n"
1328 "       gl_FrontColor = gl_Color;\n"
1329 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1330 "#endif\n"
1331 "\n"
1332 "       // transform unnormalized eye direction into tangent space\n"
1333 "#ifdef USEOFFSETMAPPING\n"
1334 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1335 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1336 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1337 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1338 "#endif\n"
1339 "\n"
1340 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1341 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1342 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1343 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1344 "}\n"
1345 "#endif // VERTEX_SHADER\n"
1346 "\n"
1347 "#ifdef FRAGMENT_SHADER\n"
1348 "void main(void)\n"
1349 "{\n"
1350 "#ifdef USEOFFSETMAPPING\n"
1351 "       // apply offsetmapping\n"
1352 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1353 "#define TexCoord TexCoordOffset\n"
1354 "#endif\n"
1355 "\n"
1356 "#ifdef USEALPHAKILL\n"
1357 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1358 "               discard;\n"
1359 "#endif\n"
1360 "\n"
1361 "#ifdef USEVERTEXTEXTUREBLEND\n"
1362 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1363 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1364 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1365 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1366 "#endif\n"
1367 "\n"
1368 "#ifdef USEVERTEXTEXTUREBLEND\n"
1369 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1370 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1371 "#else\n"
1372 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1373 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1374 "#endif\n"
1375 "\n"
1376 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1377 "}\n"
1378 "#endif // FRAGMENT_SHADER\n"
1379 "#else // !MODE_DEFERREDGEOMETRY\n"
1380 "\n"
1381 "\n"
1382 "\n"
1383 "\n"
1384 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1385 "#ifdef VERTEX_SHADER\n"
1386 "uniform mat4 ModelViewMatrix;\n"
1387 "void main(void)\n"
1388 "{\n"
1389 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1390 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1391 "}\n"
1392 "#endif // VERTEX_SHADER\n"
1393 "\n"
1394 "#ifdef FRAGMENT_SHADER\n"
1395 "uniform mat4 ViewToLight;\n"
1396 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1397 "uniform vec2 ScreenToDepth;\n"
1398 "uniform myhalf3 DeferredColor_Ambient;\n"
1399 "uniform myhalf3 DeferredColor_Diffuse;\n"
1400 "#ifdef USESPECULAR\n"
1401 "uniform myhalf3 DeferredColor_Specular;\n"
1402 "uniform myhalf SpecularPower;\n"
1403 "#endif\n"
1404 "uniform myhalf2 PixelToScreenTexCoord;\n"
1405 "void main(void)\n"
1406 "{\n"
1407 "       // calculate viewspace pixel position\n"
1408 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1409 "       vec3 position;\n"
1410 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1411 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1412 "       // decode viewspace pixel normal\n"
1413 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1414 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1415 "       // surfacenormal = pixel normal in viewspace\n"
1416 "       // LightVector = pixel to light in viewspace\n"
1417 "       // CubeVector = position in lightspace\n"
1418 "       // eyevector = pixel to view in viewspace\n"
1419 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1420 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1421 "#ifdef USEDIFFUSE\n"
1422 "       // calculate diffuse shading\n"
1423 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1424 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1425 "#endif\n"
1426 "#ifdef USESPECULAR\n"
1427 "       // calculate directional shading\n"
1428 "       vec3 eyevector = position * -1.0;\n"
1429 "#  ifdef USEEXACTSPECULARMATH\n"
1430 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1431 "#  else\n"
1432 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1433 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1434 "#  endif\n"
1435 "#endif\n"
1436 "\n"
1437 "#if defined(USESHADOWMAP2D)\n"
1438 "       fade *= ShadowMapCompare(CubeVector);\n"
1439 "#endif\n"
1440 "\n"
1441 "#ifdef USEDIFFUSE\n"
1442 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1443 "#else\n"
1444 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1445 "#endif\n"
1446 "#ifdef USESPECULAR\n"
1447 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1448 "#else\n"
1449 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1450 "#endif\n"
1451 "\n"
1452 "# ifdef USECUBEFILTER\n"
1453 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1454 "       gl_FragData[0].rgb *= cubecolor;\n"
1455 "       gl_FragData[1].rgb *= cubecolor;\n"
1456 "# endif\n"
1457 "}\n"
1458 "#endif // FRAGMENT_SHADER\n"
1459 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1460 "\n"
1461 "\n"
1462 "\n"
1463 "\n"
1464 "#ifdef VERTEX_SHADER\n"
1465 "uniform mat4 TexMatrix;\n"
1466 "#ifdef USEVERTEXTEXTUREBLEND\n"
1467 "uniform mat4 BackgroundTexMatrix;\n"
1468 "#endif\n"
1469 "#ifdef MODE_LIGHTSOURCE\n"
1470 "uniform mat4 ModelToLight;\n"
1471 "#endif\n"
1472 "#ifdef USESHADOWMAPORTHO\n"
1473 "uniform mat4 ShadowMapMatrix;\n"
1474 "#endif\n"
1475 "void main(void)\n"
1476 "{\n"
1477 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1478 "       gl_FrontColor = gl_Color;\n"
1479 "#endif\n"
1480 "       // copy the surface texcoord\n"
1481 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1482 "#ifdef USEVERTEXTEXTUREBLEND\n"
1483 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1484 "#endif\n"
1485 "#ifdef USELIGHTMAP\n"
1486 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1487 "#endif\n"
1488 "\n"
1489 "#ifdef MODE_LIGHTSOURCE\n"
1490 "       // transform vertex position into light attenuation/cubemap space\n"
1491 "       // (-1 to +1 across the light box)\n"
1492 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1493 "\n"
1494 "# ifdef USEDIFFUSE\n"
1495 "       // transform unnormalized light direction into tangent space\n"
1496 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1497 "       //  normalize it per pixel)\n"
1498 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1499 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1500 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1501 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1502 "# endif\n"
1503 "#endif\n"
1504 "\n"
1505 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1506 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1507 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1508 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1509 "#endif\n"
1510 "\n"
1511 "       // transform unnormalized eye direction into tangent space\n"
1512 "#ifdef USEEYEVECTOR\n"
1513 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1514 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1515 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1516 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1517 "#endif\n"
1518 "\n"
1519 "#ifdef USEFOG\n"
1520 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1521 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1522 "#endif\n"
1523 "\n"
1524 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1525 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1526 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1527 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1528 "#endif\n"
1529 "\n"
1530 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1531 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1532 "\n"
1533 "#ifdef USESHADOWMAPORTHO\n"
1534 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1535 "#endif\n"
1536 "\n"
1537 "#ifdef USEREFLECTION\n"
1538 "       ModelViewProjectionPosition = gl_Position;\n"
1539 "#endif\n"
1540 "}\n"
1541 "#endif // VERTEX_SHADER\n"
1542 "\n"
1543 "\n"
1544 "\n"
1545 "\n"
1546 "#ifdef FRAGMENT_SHADER\n"
1547 "#ifdef USEDEFERREDLIGHTMAP\n"
1548 "uniform myhalf2 PixelToScreenTexCoord;\n"
1549 "uniform myhalf3 DeferredMod_Diffuse;\n"
1550 "uniform myhalf3 DeferredMod_Specular;\n"
1551 "#endif\n"
1552 "uniform myhalf3 Color_Ambient;\n"
1553 "uniform myhalf3 Color_Diffuse;\n"
1554 "uniform myhalf3 Color_Specular;\n"
1555 "uniform myhalf SpecularPower;\n"
1556 "#ifdef USEGLOW\n"
1557 "uniform myhalf3 Color_Glow;\n"
1558 "#endif\n"
1559 "uniform myhalf Alpha;\n"
1560 "#ifdef USEREFLECTION\n"
1561 "uniform vec4 DistortScaleRefractReflect;\n"
1562 "uniform vec4 ScreenScaleRefractReflect;\n"
1563 "uniform vec4 ScreenCenterRefractReflect;\n"
1564 "uniform myhalf4 ReflectColor;\n"
1565 "#endif\n"
1566 "#ifdef USEREFLECTCUBE\n"
1567 "uniform mat4 ModelToReflectCube;\n"
1568 "uniform sampler2D Texture_ReflectMask;\n"
1569 "uniform samplerCube Texture_ReflectCube;\n"
1570 "#endif\n"
1571 "#ifdef MODE_LIGHTDIRECTION\n"
1572 "uniform myhalf3 LightColor;\n"
1573 "#endif\n"
1574 "#ifdef MODE_LIGHTSOURCE\n"
1575 "uniform myhalf3 LightColor;\n"
1576 "#endif\n"
1577 "void main(void)\n"
1578 "{\n"
1579 "#ifdef USEOFFSETMAPPING\n"
1580 "       // apply offsetmapping\n"
1581 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1582 "#define TexCoord TexCoordOffset\n"
1583 "#endif\n"
1584 "\n"
1585 "       // combine the diffuse textures (base, pants, shirt)\n"
1586 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1587 "#ifdef USEALPHAKILL\n"
1588 "       if (color.a < 0.5)\n"
1589 "               discard;\n"
1590 "#endif\n"
1591 "       color.a *= Alpha;\n"
1592 "#ifdef USECOLORMAPPING\n"
1593 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1594 "#endif\n"
1595 "#ifdef USEVERTEXTEXTUREBLEND\n"
1596 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1597 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1598 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1599 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1600 "       color.a = 1.0;\n"
1601 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1602 "#endif\n"
1603 "\n"
1604 "       // get the surface normal\n"
1605 "#ifdef USEVERTEXTEXTUREBLEND\n"
1606 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1607 "#else\n"
1608 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1609 "#endif\n"
1610 "\n"
1611 "       // get the material colors\n"
1612 "       myhalf3 diffusetex = color.rgb;\n"
1613 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1614 "# ifdef USEVERTEXTEXTUREBLEND\n"
1615 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1616 "# else\n"
1617 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1618 "# endif\n"
1619 "#endif\n"
1620 "\n"
1621 "#ifdef USEREFLECTCUBE\n"
1622 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1623 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1624 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1625 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1626 "#endif\n"
1627 "\n"
1628 "\n"
1629 "\n"
1630 "\n"
1631 "#ifdef MODE_LIGHTSOURCE\n"
1632 "       // light source\n"
1633 "#ifdef USEDIFFUSE\n"
1634 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1635 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1636 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1637 "#ifdef USESPECULAR\n"
1638 "#ifdef USEEXACTSPECULARMATH\n"
1639 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1640 "#else\n"
1641 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1642 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1643 "#endif\n"
1644 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1645 "#endif\n"
1646 "#else\n"
1647 "       color.rgb = diffusetex * Color_Ambient;\n"
1648 "#endif\n"
1649 "       color.rgb *= LightColor;\n"
1650 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1651 "#if defined(USESHADOWMAP2D)\n"
1652 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1653 "#endif\n"
1654 "# ifdef USECUBEFILTER\n"
1655 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1656 "# endif\n"
1657 "#endif // MODE_LIGHTSOURCE\n"
1658 "\n"
1659 "\n"
1660 "\n"
1661 "\n"
1662 "#ifdef MODE_LIGHTDIRECTION\n"
1663 "#define SHADING\n"
1664 "#ifdef USEDIFFUSE\n"
1665 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1666 "#endif\n"
1667 "#define lightcolor LightColor\n"
1668 "#endif // MODE_LIGHTDIRECTION\n"
1669 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1670 "#define SHADING\n"
1671 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1672 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1673 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1674 "       // convert modelspace light vector to tangentspace\n"
1675 "       myhalf3 lightnormal;\n"
1676 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1677 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1678 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1679 "       lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
1680 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1681 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1682 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1683 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1684 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1685 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1686 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1687 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1688 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1689 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1690 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1691 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1692 "#define SHADING\n"
1693 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1694 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1695 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1696 "#endif\n"
1697 "\n"
1698 "\n"
1699 "\n"
1700 "\n"
1701 "#ifdef MODE_FAKELIGHT\n"
1702 "#define SHADING\n"
1703 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1704 "myhalf3 lightcolor = myhalf3(1.0);\n"
1705 "#endif // MODE_FAKELIGHT\n"
1706 "\n"
1707 "\n"
1708 "\n"
1709 "\n"
1710 "#ifdef MODE_LIGHTMAP\n"
1711 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1712 "#endif // MODE_LIGHTMAP\n"
1713 "#ifdef MODE_VERTEXCOLOR\n"
1714 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1715 "#endif // MODE_VERTEXCOLOR\n"
1716 "#ifdef MODE_FLATCOLOR\n"
1717 "       color.rgb = diffusetex * Color_Ambient;\n"
1718 "#endif // MODE_FLATCOLOR\n"
1719 "\n"
1720 "\n"
1721 "\n"
1722 "\n"
1723 "#ifdef SHADING\n"
1724 "# ifdef USEDIFFUSE\n"
1725 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1726 "#  ifdef USESPECULAR\n"
1727 "#   ifdef USEEXACTSPECULARMATH\n"
1728 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1729 "#   else\n"
1730 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1731 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1732 "#   endif\n"
1733 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1734 "#  else\n"
1735 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1736 "#  endif\n"
1737 "# else\n"
1738 "       color.rgb = diffusetex * Color_Ambient;\n"
1739 "# endif\n"
1740 "#endif\n"
1741 "\n"
1742 "#ifdef USESHADOWMAPORTHO\n"
1743 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1744 "#endif\n"
1745 "\n"
1746 "#ifdef USEDEFERREDLIGHTMAP\n"
1747 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1748 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1749 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1750 "#endif\n"
1751 "\n"
1752 "#ifdef USEGLOW\n"
1753 "#ifdef USEVERTEXTEXTUREBLEND\n"
1754 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1755 "#else\n"
1756 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1757 "#endif\n"
1758 "#endif\n"
1759 "\n"
1760 "#ifdef USEFOG\n"
1761 "       color.rgb = FogVertex(color.rgb);\n"
1762 "#endif\n"
1763 "\n"
1764 "       // 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"
1765 "#ifdef USEREFLECTION\n"
1766 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1767 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1768 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1769 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1770 "       // FIXME temporary hack to detect the case that the reflection\n"
1771 "       // gets blackened at edges due to leaving the area that contains actual\n"
1772 "       // content.\n"
1773 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1774 "       // 'appening.\n"
1775 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1776 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1777 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1778 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1779 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1780 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1781 "#endif\n"
1782 "\n"
1783 "       gl_FragColor = vec4(color);\n"
1784 "}\n"
1785 "#endif // FRAGMENT_SHADER\n"
1786 "\n"
1787 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1788 "#endif // !MODE_DEFERREDGEOMETRY\n"
1789 "#endif // !MODE_WATER\n"
1790 "#endif // !MODE_REFRACTION\n"
1791 "#endif // !MODE_BLOOMBLUR\n"
1792 "#endif // !MODE_GENERIC\n"
1793 "#endif // !MODE_POSTPROCESS\n"
1794 "#endif // !MODE_SHOWDEPTH\n"
1795 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1796 ;
1797
1798 /*
1799 =========================================================================================================================================================
1800
1801
1802
1803 =========================================================================================================================================================
1804
1805
1806
1807 =========================================================================================================================================================
1808
1809
1810
1811 =========================================================================================================================================================
1812
1813
1814
1815 =========================================================================================================================================================
1816
1817
1818
1819 =========================================================================================================================================================
1820
1821
1822
1823 =========================================================================================================================================================
1824 */
1825
1826 const char *builtincgshaderstring =
1827 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1828 "// written by Forest 'LordHavoc' Hale\n"
1829 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1830 "\n"
1831 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1832 "#if defined(USEREFLECTION)\n"
1833 "#undef USESHADOWMAPORTHO\n"
1834 "#endif\n"
1835 "\n"
1836 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1837 "# define USEFOG\n"
1838 "#endif\n"
1839 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1840 "#define USELIGHTMAP\n"
1841 "#endif\n"
1842 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1843 "#define USEEYEVECTOR\n"
1844 "#endif\n"
1845 "\n"
1846 "#ifdef FRAGMENT_SHADER\n"
1847 "#ifdef HLSL\n"
1848 "//#undef USESHADOWMAPPCF\n"
1849 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1850 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1851 "#else\n"
1852 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1853 "#endif\n"
1854 "#endif\n"
1855 "\n"
1856 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1857 "#ifdef VERTEX_SHADER\n"
1858 "void main\n"
1859 "(\n"
1860 "float4 gl_Vertex : POSITION,\n"
1861 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1862 "out float4 gl_Position : POSITION,\n"
1863 "out float Depth : TEXCOORD0\n"
1864 ")\n"
1865 "{\n"
1866 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1867 "       Depth = gl_Position.z;\n"
1868 "}\n"
1869 "#endif\n"
1870 "\n"
1871 "#ifdef FRAGMENT_SHADER\n"
1872 "void main\n"
1873 "(\n"
1874 "float Depth : TEXCOORD0,\n"
1875 "out float4 gl_FragColor : COLOR\n"
1876 ")\n"
1877 "{\n"
1878 "//     float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1879 "       float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1880 "       temp.yz -= floor(temp.yz);\n"
1881 "       gl_FragColor = temp;\n"
1882 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1883 "}\n"
1884 "#endif\n"
1885 "#else // !MODE_DEPTH_ORSHADOW\n"
1886 "\n"
1887 "\n"
1888 "\n"
1889 "\n"
1890 "#ifdef MODE_SHOWDEPTH\n"
1891 "#ifdef VERTEX_SHADER\n"
1892 "void main\n"
1893 "(\n"
1894 "float4 gl_Vertex : POSITION,\n"
1895 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1896 "out float4 gl_Position : POSITION,\n"
1897 "out float4 gl_FrontColor : COLOR0\n"
1898 ")\n"
1899 "{\n"
1900 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1901 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1902 "}\n"
1903 "#endif\n"
1904 "\n"
1905 "#ifdef FRAGMENT_SHADER\n"
1906 "void main\n"
1907 "(\n"
1908 "float4 gl_FrontColor : COLOR0,\n"
1909 "out float4 gl_FragColor : COLOR\n"
1910 ")\n"
1911 "{\n"
1912 "       gl_FragColor = gl_FrontColor;\n"
1913 "}\n"
1914 "#endif\n"
1915 "#else // !MODE_SHOWDEPTH\n"
1916 "\n"
1917 "\n"
1918 "\n"
1919 "\n"
1920 "#ifdef MODE_POSTPROCESS\n"
1921 "\n"
1922 "#ifdef VERTEX_SHADER\n"
1923 "void main\n"
1924 "(\n"
1925 "float4 gl_Vertex : POSITION,\n"
1926 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1927 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1928 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1929 "out float4 gl_Position : POSITION,\n"
1930 "out float2 TexCoord1 : TEXCOORD0,\n"
1931 "out float2 TexCoord2 : TEXCOORD1\n"
1932 ")\n"
1933 "{\n"
1934 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1935 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1936 "#ifdef USEBLOOM\n"
1937 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1938 "#endif\n"
1939 "}\n"
1940 "#endif\n"
1941 "\n"
1942 "#ifdef FRAGMENT_SHADER\n"
1943 "void main\n"
1944 "(\n"
1945 "float2 TexCoord1 : TEXCOORD0,\n"
1946 "float2 TexCoord2 : TEXCOORD1,\n"
1947 "uniform sampler Texture_First : register(s0),\n"
1948 "#ifdef USEBLOOM\n"
1949 "uniform sampler Texture_Second : register(s1),\n"
1950 "#endif\n"
1951 "#ifdef USEGAMMARAMPS\n"
1952 "uniform sampler Texture_GammaRamps : register(s2),\n"
1953 "#endif\n"
1954 "#ifdef USESATURATION\n"
1955 "uniform float Saturation : register(c30),\n"
1956 "#endif\n"
1957 "#ifdef USEVIEWTINT\n"
1958 "uniform float4 ViewTintColor : register(c41),\n"
1959 "#endif\n"
1960 "uniform float4 UserVec1 : register(c37),\n"
1961 "uniform float4 UserVec2 : register(c38),\n"
1962 "uniform float4 UserVec3 : register(c39),\n"
1963 "uniform float4 UserVec4 : register(c40),\n"
1964 "uniform float ClientTime : register(c2),\n"
1965 "uniform float2 PixelSize : register(c25),\n"
1966 "uniform float4 BloomColorSubtract : register(c43),\n"
1967 "out float4 gl_FragColor : COLOR\n"
1968 ")\n"
1969 "{\n"
1970 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1971 "#ifdef USEBLOOM\n"
1972 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1973 "#endif\n"
1974 "#ifdef USEVIEWTINT\n"
1975 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1976 "#endif\n"
1977 "\n"
1978 "#ifdef USEPOSTPROCESSING\n"
1979 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1980 "// 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"
1981 "       float sobel = 1.0;\n"
1982 "       // float2 ts = textureSize(Texture_First, 0);\n"
1983 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
1984 "       float2 px = PixelSize;\n"
1985 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1986 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
1987 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1988 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1989 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
1990 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1991 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1992 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
1993 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1994 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1995 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
1996 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1997 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
1998 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
1999 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2000 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2001 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2002 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2003 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2004 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2005 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2006 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2007 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2008 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2009 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2010 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2011 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2012 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2013 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2014 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2015 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2016 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2017 "#endif\n"
2018 "\n"
2019 "#ifdef USESATURATION\n"
2020 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2021 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2022 "       // 'vampire sight' effect, wheres red is compensated\n"
2023 "       #ifdef SATURATION_REDCOMPENSATE\n"
2024 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2025 "               gl_FragColor.rgb = mix(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2026 "               gl_FragColor.r += r;\n"
2027 "       #else\n"
2028 "               // normal desaturation\n"
2029 "               //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2030 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2031 "       #endif\n"
2032 "#endif\n"
2033 "\n"
2034 "#ifdef USEGAMMARAMPS\n"
2035 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2036 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2037 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2038 "#endif\n"
2039 "}\n"
2040 "#endif\n"
2041 "#else // !MODE_POSTPROCESS\n"
2042 "\n"
2043 "\n"
2044 "\n"
2045 "\n"
2046 "#ifdef MODE_GENERIC\n"
2047 "#ifdef VERTEX_SHADER\n"
2048 "void main\n"
2049 "(\n"
2050 "float4 gl_Vertex : POSITION,\n"
2051 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2052 "float4 gl_Color : COLOR0,\n"
2053 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2054 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2055 "out float4 gl_Position : POSITION,\n"
2056 "#ifdef USEDIFFUSE\n"
2057 "out float2 TexCoord1 : TEXCOORD0,\n"
2058 "#endif\n"
2059 "#ifdef USESPECULAR\n"
2060 "out float2 TexCoord2 : TEXCOORD1,\n"
2061 "#endif\n"
2062 "out float4 gl_FrontColor : COLOR\n"
2063 ")\n"
2064 "{\n"
2065 "#ifdef HLSL\n"
2066 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2067 "#else\n"
2068 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2069 "#endif\n"
2070 "#ifdef USEDIFFUSE\n"
2071 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2072 "#endif\n"
2073 "#ifdef USESPECULAR\n"
2074 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2075 "#endif\n"
2076 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2077 "}\n"
2078 "#endif\n"
2079 "\n"
2080 "#ifdef FRAGMENT_SHADER\n"
2081 "\n"
2082 "void main\n"
2083 "(\n"
2084 "float4 gl_FrontColor : COLOR0,\n"
2085 "float2 TexCoord1 : TEXCOORD0,\n"
2086 "float2 TexCoord2 : TEXCOORD1,\n"
2087 "#ifdef USEDIFFUSE\n"
2088 "uniform sampler Texture_First : register(s0),\n"
2089 "#endif\n"
2090 "#ifdef USESPECULAR\n"
2091 "uniform sampler Texture_Second : register(s1),\n"
2092 "#endif\n"
2093 "out float4 gl_FragColor : COLOR\n"
2094 ")\n"
2095 "{\n"
2096 "#ifdef USEVIEWTINT\n"
2097 "       gl_FragColor = gl_FrontColor;\n"
2098 "#else\n"
2099 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
2100 "#endif\n"
2101 "#ifdef USEDIFFUSE\n"
2102 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2103 "#endif\n"
2104 "\n"
2105 "#ifdef USESPECULAR\n"
2106 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2107 "# ifdef USECOLORMAPPING\n"
2108 "       gl_FragColor *= tex2;\n"
2109 "# endif\n"
2110 "# ifdef USEGLOW\n"
2111 "       gl_FragColor += tex2;\n"
2112 "# endif\n"
2113 "# ifdef USEVERTEXTEXTUREBLEND\n"
2114 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2115 "# endif\n"
2116 "#endif\n"
2117 "}\n"
2118 "#endif\n"
2119 "#else // !MODE_GENERIC\n"
2120 "\n"
2121 "\n"
2122 "\n"
2123 "\n"
2124 "#ifdef MODE_BLOOMBLUR\n"
2125 "#ifdef VERTEX_SHADER\n"
2126 "void main\n"
2127 "(\n"
2128 "float4 gl_Vertex : POSITION,\n"
2129 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2130 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2131 "out float4 gl_Position : POSITION,\n"
2132 "out float2 TexCoord : TEXCOORD0\n"
2133 ")\n"
2134 "{\n"
2135 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2136 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2137 "}\n"
2138 "#endif\n"
2139 "\n"
2140 "#ifdef FRAGMENT_SHADER\n"
2141 "\n"
2142 "void main\n"
2143 "(\n"
2144 "float2 TexCoord : TEXCOORD0,\n"
2145 "uniform sampler Texture_First : register(s0),\n"
2146 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2147 "out float4 gl_FragColor : COLOR\n"
2148 ")\n"
2149 "{\n"
2150 "       int i;\n"
2151 "       float2 tc = TexCoord;\n"
2152 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2153 "       tc += BloomBlur_Parameters.xy;\n"
2154 "       for (i = 1;i < SAMPLES;i++)\n"
2155 "       {\n"
2156 "               color += tex2D(Texture_First, tc).rgb;\n"
2157 "               tc += BloomBlur_Parameters.xy;\n"
2158 "       }\n"
2159 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2160 "}\n"
2161 "#endif\n"
2162 "#else // !MODE_BLOOMBLUR\n"
2163 "#ifdef MODE_REFRACTION\n"
2164 "#ifdef VERTEX_SHADER\n"
2165 "void main\n"
2166 "(\n"
2167 "float4 gl_Vertex : POSITION,\n"
2168 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2169 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2170 "uniform float4x4 TexMatrix : register(c0),\n"
2171 "uniform float3 EyePosition : register(c24),\n"
2172 "out float4 gl_Position : POSITION,\n"
2173 "out float2 TexCoord : TEXCOORD0,\n"
2174 "out float3 EyeVector : TEXCOORD1,\n"
2175 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2176 ")\n"
2177 "{\n"
2178 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2179 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2180 "       ModelViewProjectionPosition = gl_Position;\n"
2181 "}\n"
2182 "#endif\n"
2183 "\n"
2184 "#ifdef FRAGMENT_SHADER\n"
2185 "void main\n"
2186 "(\n"
2187 "float2 TexCoord : TEXCOORD0,\n"
2188 "float3 EyeVector : TEXCOORD1,\n"
2189 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2190 "uniform sampler Texture_Normal : register(s0),\n"
2191 "uniform sampler Texture_Refraction : register(s3),\n"
2192 "uniform sampler Texture_Reflection : register(s7),\n"
2193 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2194 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2195 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2196 "uniform float4 RefractColor : register(c29),\n"
2197 "out float4 gl_FragColor : COLOR\n"
2198 ")\n"
2199 "{\n"
2200 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2201 "       //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"
2202 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2203 "       float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2204 "       // FIXME temporary hack to detect the case that the reflection\n"
2205 "       // gets blackened at edges due to leaving the area that contains actual\n"
2206 "       // content.\n"
2207 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2208 "       // 'appening.\n"
2209 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2210 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2211 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2212 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2213 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2214 "       gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2215 "}\n"
2216 "#endif\n"
2217 "#else // !MODE_REFRACTION\n"
2218 "\n"
2219 "\n"
2220 "\n"
2221 "\n"
2222 "#ifdef MODE_WATER\n"
2223 "#ifdef VERTEX_SHADER\n"
2224 "\n"
2225 "void main\n"
2226 "(\n"
2227 "float4 gl_Vertex : POSITION,\n"
2228 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2229 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2230 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2231 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2232 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2233 "uniform float4x4 TexMatrix : register(c0),\n"
2234 "uniform float3 EyePosition : register(c24),\n"
2235 "out float4 gl_Position : POSITION,\n"
2236 "out float2 TexCoord : TEXCOORD0,\n"
2237 "out float3 EyeVector : TEXCOORD1,\n"
2238 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2239 ")\n"
2240 "{\n"
2241 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2242 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2243 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2244 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2245 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2246 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2247 "       ModelViewProjectionPosition = gl_Position;\n"
2248 "}\n"
2249 "#endif\n"
2250 "\n"
2251 "#ifdef FRAGMENT_SHADER\n"
2252 "void main\n"
2253 "(\n"
2254 "float2 TexCoord : TEXCOORD0,\n"
2255 "float3 EyeVector : TEXCOORD1,\n"
2256 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2257 "uniform sampler Texture_Normal : register(s0),\n"
2258 "uniform sampler Texture_Refraction : register(s3),\n"
2259 "uniform sampler Texture_Reflection : register(s7),\n"
2260 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2261 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2262 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2263 "uniform float4 RefractColor : register(c29),\n"
2264 "uniform float4 ReflectColor : register(c26),\n"
2265 "uniform float ReflectFactor : register(c27),\n"
2266 "uniform float ReflectOffset : register(c28),\n"
2267 "out float4 gl_FragColor : COLOR\n"
2268 ")\n"
2269 "{\n"
2270 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2271 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2272 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2273 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2274 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2275 "       // FIXME temporary hack to detect the case that the reflection\n"
2276 "       // gets blackened at edges due to leaving the area that contains actual\n"
2277 "       // content.\n"
2278 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2279 "       // 'appening.\n"
2280 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2281 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2282 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2283 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2284 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2285 "       f  = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2286 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2287 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2288 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2289 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2290 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2291 "       gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2292 "}\n"
2293 "#endif\n"
2294 "#else // !MODE_WATER\n"
2295 "\n"
2296 "\n"
2297 "\n"
2298 "\n"
2299 "// 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"
2300 "\n"
2301 "// fragment shader specific:\n"
2302 "#ifdef FRAGMENT_SHADER\n"
2303 "\n"
2304 "#ifdef USEFOG\n"
2305 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2306 "{\n"
2307 "       float fogfrac;\n"
2308 "#ifdef USEFOGHEIGHTTEXTURE\n"
2309 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2310 "       fogfrac = fogheightpixel.a;\n"
2311 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2312 "#else\n"
2313 "# ifdef USEFOGOUTSIDE\n"
2314 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2315 "# else\n"
2316 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2317 "# endif\n"
2318 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2319 "#endif\n"
2320 "}\n"
2321 "#endif\n"
2322 "\n"
2323 "#ifdef USEOFFSETMAPPING\n"
2324 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2325 "{\n"
2326 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2327 "       // 14 sample relief mapping: linear search and then binary search\n"
2328 "       // this basically steps forward a small amount repeatedly until it finds\n"
2329 "       // itself inside solid, then jitters forward and back using decreasing\n"
2330 "       // amounts to find the impact\n"
2331 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2332 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2333 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2334 "       float3 RT = float3(TexCoord, 1);\n"
2335 "       OffsetVector *= 0.1;\n"
2336 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2337 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2338 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2339 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2340 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2341 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2342 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2343 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2344 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2345 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2346 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2347 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2348 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2349 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2350 "       return RT.xy;\n"
2351 "#else\n"
2352 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2353 "       // this basically moves forward the full distance, and then backs up based\n"
2354 "       // on height of samples\n"
2355 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2356 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2357 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2358 "       TexCoord += OffsetVector;\n"
2359 "       OffsetVector *= 0.333;\n"
2360 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2361 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2362 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2363 "       return TexCoord;\n"
2364 "#endif\n"
2365 "}\n"
2366 "#endif // USEOFFSETMAPPING\n"
2367 "\n"
2368 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2369 "#if defined(USESHADOWMAP2D)\n"
2370 "# ifdef USESHADOWMAPORTHO\n"
2371 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2372 "# else\n"
2373 "#  ifdef USESHADOWMAPVSDCT\n"
2374 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2375 "{\n"
2376 "       float3 adir = abs(dir);\n"
2377 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2378 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2379 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2380 "}\n"
2381 "#  else\n"
2382 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2383 "{\n"
2384 "       float3 adir = abs(dir);\n"
2385 "       float ma = adir.z;\n"
2386 "       float4 proj = float4(dir, 2.5);\n"
2387 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2388 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2389 "#ifdef HLSL\n"
2390 "       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"
2391 "#else\n"
2392 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2393 "       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"
2394 "#endif\n"
2395 "}\n"
2396 "#  endif\n"
2397 "# endif\n"
2398 "#endif // defined(USESHADOWMAP2D)\n"
2399 "\n"
2400 "# ifdef USESHADOWMAP2D\n"
2401 "#ifdef USESHADOWMAPVSDCT\n"
2402 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2403 "#else\n"
2404 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2405 "#endif\n"
2406 "{\n"
2407 "#ifdef USESHADOWMAPVSDCT\n"
2408 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2409 "#else\n"
2410 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2411 "#endif\n"
2412 "       float f;\n"
2413 "\n"
2414 "#  ifdef USESHADOWSAMPLER\n"
2415 "#    ifdef USESHADOWMAPPCF\n"
2416 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2417 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2418 "       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"
2419 "#    else\n"
2420 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2421 "#    endif\n"
2422 "#  else\n"
2423 "#    ifdef USESHADOWMAPPCF\n"
2424 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2425 "#      ifdef GL_ARB_texture_gather\n"
2426 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2427 "#      else\n"
2428 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2429 "#      endif\n"
2430 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2431 "#      if USESHADOWMAPPCF > 1\n"
2432 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2433 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2434 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2435 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2436 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2437 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2438 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2439 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2440 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2441 "       float4 locols = float4(group1.ab, group3.ab);\n"
2442 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2443 "       locols.yz += group2.ab;\n"
2444 "       hicols.yz += group8.rg;\n"
2445 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2446 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2447 "                               lerp(locols, hicols, offset.y);\n"
2448 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2449 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2450 "       f = dot(cols, float4(1.0/25.0));\n"
2451 "#      else\n"
2452 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2453 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2454 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2455 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2456 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2457 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2458 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2459 "#      endif\n"
2460 "#     else\n"
2461 "#      ifdef GL_EXT_gpu_shader4\n"
2462 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2463 "#      else\n"
2464 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2465 "#      endif\n"
2466 "#      if USESHADOWMAPPCF > 1\n"
2467 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2468 "       center *= ShadowMap_TextureScale;\n"
2469 "       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"
2470 "       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"
2471 "       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"
2472 "       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"
2473 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2474 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2475 "#      else\n"
2476 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2477 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2478 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2479 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2480 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2481 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2482 "#      endif\n"
2483 "#     endif\n"
2484 "#    else\n"
2485 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2486 "#    endif\n"
2487 "#  endif\n"
2488 "#  ifdef USESHADOWMAPORTHO\n"
2489 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2490 "#  else\n"
2491 "       return f;\n"
2492 "#  endif\n"
2493 "}\n"
2494 "# endif\n"
2495 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2496 "#endif // FRAGMENT_SHADER\n"
2497 "\n"
2498 "\n"
2499 "\n"
2500 "\n"
2501 "#ifdef MODE_DEFERREDGEOMETRY\n"
2502 "#ifdef VERTEX_SHADER\n"
2503 "void main\n"
2504 "(\n"
2505 "float4 gl_Vertex : POSITION,\n"
2506 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2507 "#ifdef USEVERTEXTEXTUREBLEND\n"
2508 "float4 gl_Color : COLOR0,\n"
2509 "#endif\n"
2510 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2511 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2512 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2513 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2514 "uniform float4x4 TexMatrix : register(c0),\n"
2515 "#ifdef USEVERTEXTEXTUREBLEND\n"
2516 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2517 "#endif\n"
2518 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2519 "#ifdef USEOFFSETMAPPING\n"
2520 "uniform float3 EyePosition : register(c24),\n"
2521 "#endif\n"
2522 "out float4 gl_Position : POSITION,\n"
2523 "#ifdef USEVERTEXTEXTUREBLEND\n"
2524 "out float4 gl_FrontColor : COLOR,\n"
2525 "#endif\n"
2526 "out float4 TexCoordBoth : TEXCOORD0,\n"
2527 "#ifdef USEOFFSETMAPPING\n"
2528 "out float3 EyeVector : TEXCOORD2,\n"
2529 "#endif\n"
2530 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2531 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2532 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2533 ")\n"
2534 "{\n"
2535 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2536 "#ifdef USEVERTEXTEXTUREBLEND\n"
2537 "#ifdef HLSL\n"
2538 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2539 "#else\n"
2540 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2541 "#endif\n"
2542 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2543 "#endif\n"
2544 "\n"
2545 "       // transform unnormalized eye direction into tangent space\n"
2546 "#ifdef USEOFFSETMAPPING\n"
2547 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2548 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2549 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2550 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2551 "#endif\n"
2552 "\n"
2553 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2554 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2555 "       VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2556 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2557 "       VectorR.w = gl_Position.z;\n"
2558 "}\n"
2559 "#endif // VERTEX_SHADER\n"
2560 "\n"
2561 "#ifdef FRAGMENT_SHADER\n"
2562 "void main\n"
2563 "(\n"
2564 "float4 TexCoordBoth : TEXCOORD0,\n"
2565 "float3 EyeVector : TEXCOORD2,\n"
2566 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2567 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2568 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2569 "uniform sampler Texture_Normal : register(s0),\n"
2570 "#ifdef USEALPHAKILL\n"
2571 "uniform sampler Texture_Color : register(s1),\n"
2572 "#endif\n"
2573 "uniform sampler Texture_Gloss : register(s2),\n"
2574 "#ifdef USEVERTEXTEXTUREBLEND\n"
2575 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2576 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2577 "#endif\n"
2578 "#ifdef USEOFFSETMAPPING\n"
2579 "uniform float OffsetMapping_Scale : register(c24),\n"
2580 "#endif\n"
2581 "uniform half SpecularPower : register(c36),\n"
2582 "#ifdef HLSL\n"
2583 "out float4 gl_FragData0 : COLOR0,\n"
2584 "out float4 gl_FragData1 : COLOR1\n"
2585 "#else\n"
2586 "out float4 gl_FragColor : COLOR\n"
2587 "#endif\n"
2588 ")\n"
2589 "{\n"
2590 "       float2 TexCoord = TexCoordBoth.xy;\n"
2591 "#ifdef USEOFFSETMAPPING\n"
2592 "       // apply offsetmapping\n"
2593 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2594 "#define TexCoord TexCoordOffset\n"
2595 "#endif\n"
2596 "\n"
2597 "#ifdef USEALPHAKILL\n"
2598 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2599 "               discard;\n"
2600 "#endif\n"
2601 "\n"
2602 "#ifdef USEVERTEXTEXTUREBLEND\n"
2603 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2604 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2605 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2606 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2607 "#endif\n"
2608 "\n"
2609 "#ifdef USEVERTEXTEXTUREBLEND\n"
2610 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2611 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2612 "#else\n"
2613 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2614 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2615 "#endif\n"
2616 "\n"
2617 "#ifdef HLSL\n"
2618 "       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"
2619 "       float Depth = VectorR.w / 256.0;\n"
2620 "       float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2621 "//     float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2622 "       depthcolor.yz -= floor(depthcolor.yz);\n"
2623 "       gl_FragData1 = depthcolor;\n"
2624 "#else\n"
2625 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2626 "#endif\n"
2627 "}\n"
2628 "#endif // FRAGMENT_SHADER\n"
2629 "#else // !MODE_DEFERREDGEOMETRY\n"
2630 "\n"
2631 "\n"
2632 "\n"
2633 "\n"
2634 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2635 "#ifdef VERTEX_SHADER\n"
2636 "void main\n"
2637 "(\n"
2638 "float4 gl_Vertex : POSITION,\n"
2639 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2640 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2641 "out float4 gl_Position : POSITION,\n"
2642 "out float4 ModelViewPosition : TEXCOORD0\n"
2643 ")\n"
2644 "{\n"
2645 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2646 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2647 "}\n"
2648 "#endif // VERTEX_SHADER\n"
2649 "\n"
2650 "#ifdef FRAGMENT_SHADER\n"
2651 "void main\n"
2652 "(\n"
2653 "#ifdef HLSL\n"
2654 "float2 Pixel : VPOS,\n"
2655 "#else\n"
2656 "float2 Pixel : WPOS,\n"
2657 "#endif\n"
2658 "float4 ModelViewPosition : TEXCOORD0,\n"
2659 "uniform float4x4 ViewToLight : register(c44),\n"
2660 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2661 "uniform float3 LightPosition : register(c23),\n"
2662 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2663 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2664 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2665 "#ifdef USESPECULAR\n"
2666 "uniform half3 DeferredColor_Specular : register(c11),\n"
2667 "uniform half SpecularPower : register(c36),\n"
2668 "#endif\n"
2669 "uniform sampler Texture_Attenuation : register(s9),\n"
2670 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2671 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2672 "\n"
2673 "#ifdef USECUBEFILTER\n"
2674 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2675 "#endif\n"
2676 "\n"
2677 "#ifdef USESHADOWMAP2D\n"
2678 "# ifdef USESHADOWSAMPLER\n"
2679 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2680 "# else\n"
2681 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2682 "# endif\n"
2683 "#endif\n"
2684 "\n"
2685 "#ifdef USESHADOWMAPVSDCT\n"
2686 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2687 "#endif\n"
2688 "\n"
2689 "#if defined(USESHADOWMAP2D)\n"
2690 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2691 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2692 "#endif\n"
2693 "\n"
2694 "out float4 gl_FragData0 : COLOR0,\n"
2695 "out float4 gl_FragData1 : COLOR1\n"
2696 ")\n"
2697 "{\n"
2698 "       // calculate viewspace pixel position\n"
2699 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2700 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2701 "       float3 position;\n"
2702 "#ifdef HLSL\n"
2703 "       position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2704 "#else\n"
2705 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2706 "#endif\n"
2707 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2708 "       // decode viewspace pixel normal\n"
2709 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2710 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2711 "       // surfacenormal = pixel normal in viewspace\n"
2712 "       // LightVector = pixel to light in viewspace\n"
2713 "       // CubeVector = position in lightspace\n"
2714 "       // eyevector = pixel to view in viewspace\n"
2715 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2716 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2717 "#ifdef USEDIFFUSE\n"
2718 "       // calculate diffuse shading\n"
2719 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2720 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2721 "#endif\n"
2722 "#ifdef USESPECULAR\n"
2723 "       // calculate directional shading\n"
2724 "       float3 eyevector = position * -1.0;\n"
2725 "#  ifdef USEEXACTSPECULARMATH\n"
2726 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2727 "#  else\n"
2728 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2729 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2730 "#  endif\n"
2731 "#endif\n"
2732 "\n"
2733 "#if defined(USESHADOWMAP2D)\n"
2734 "       fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2735 "#ifdef USESHADOWMAPVSDCT\n"
2736 ", Texture_CubeProjection\n"
2737 "#endif\n"
2738 "       ));\n"
2739 "#endif\n"
2740 "\n"
2741 "#ifdef USEDIFFUSE\n"
2742 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2743 "#else\n"
2744 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2745 "#endif\n"
2746 "#ifdef USESPECULAR\n"
2747 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2748 "#else\n"
2749 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2750 "#endif\n"
2751 "\n"
2752 "# ifdef USECUBEFILTER\n"
2753 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2754 "       gl_FragData0.rgb *= cubecolor;\n"
2755 "       gl_FragData1.rgb *= cubecolor;\n"
2756 "# endif\n"
2757 "}\n"
2758 "#endif // FRAGMENT_SHADER\n"
2759 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2760 "\n"
2761 "\n"
2762 "\n"
2763 "\n"
2764 "#ifdef VERTEX_SHADER\n"
2765 "void main\n"
2766 "(\n"
2767 "float4 gl_Vertex : POSITION,\n"
2768 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2769 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2770 "float4 gl_Color : COLOR0,\n"
2771 "#endif\n"
2772 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2773 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2774 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2775 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2776 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2777 "\n"
2778 "uniform float3 EyePosition : register(c24),\n"
2779 "uniform float4x4 TexMatrix : register(c0),\n"
2780 "#ifdef USEVERTEXTEXTUREBLEND\n"
2781 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2782 "#endif\n"
2783 "#ifdef MODE_LIGHTSOURCE\n"
2784 "uniform float4x4 ModelToLight : register(c20),\n"
2785 "#endif\n"
2786 "#ifdef MODE_LIGHTSOURCE\n"
2787 "uniform float3 LightPosition : register(c27),\n"
2788 "#endif\n"
2789 "#ifdef MODE_LIGHTDIRECTION\n"
2790 "uniform float3 LightDir : register(c26),\n"
2791 "#endif\n"
2792 "uniform float4 FogPlane : register(c25),\n"
2793 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2794 "uniform float3 LightPosition : register(c27),\n"
2795 "#endif\n"
2796 "#ifdef USESHADOWMAPORTHO\n"
2797 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2798 "#endif\n"
2799 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2800 "out float4 gl_FrontColor : COLOR,\n"
2801 "#endif\n"
2802 "out float4 TexCoordBoth : TEXCOORD0,\n"
2803 "#ifdef USELIGHTMAP\n"
2804 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2805 "#endif\n"
2806 "#ifdef USEEYEVECTOR\n"
2807 "out float3 EyeVector : TEXCOORD2,\n"
2808 "#endif\n"
2809 "#ifdef USEREFLECTION\n"
2810 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2811 "#endif\n"
2812 "#ifdef USEFOG\n"
2813 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2814 "#endif\n"
2815 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2816 "out float3 LightVector : TEXCOORD1,\n"
2817 "#endif\n"
2818 "#ifdef MODE_LIGHTSOURCE\n"
2819 "out float3 CubeVector : TEXCOORD3,\n"
2820 "#endif\n"
2821 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2822 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2823 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2824 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2825 "#endif\n"
2826 "#ifdef USESHADOWMAPORTHO\n"
2827 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2828 "#endif\n"
2829 "out float4 gl_Position : POSITION\n"
2830 ")\n"
2831 "{\n"
2832 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2833 "#ifdef HLSL\n"
2834 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2835 "#else\n"
2836 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2837 "#endif\n"
2838 "#endif\n"
2839 "       // copy the surface texcoord\n"
2840 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2841 "#ifdef USEVERTEXTEXTUREBLEND\n"
2842 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2843 "#endif\n"
2844 "#ifdef USELIGHTMAP\n"
2845 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2846 "#endif\n"
2847 "\n"
2848 "#ifdef MODE_LIGHTSOURCE\n"
2849 "       // transform vertex position into light attenuation/cubemap space\n"
2850 "       // (-1 to +1 across the light box)\n"
2851 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2852 "\n"
2853 "# ifdef USEDIFFUSE\n"
2854 "       // transform unnormalized light direction into tangent space\n"
2855 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2856 "       //  normalize it per pixel)\n"
2857 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2858 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2859 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2860 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2861 "# endif\n"
2862 "#endif\n"
2863 "\n"
2864 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2865 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2866 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2867 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2868 "#endif\n"
2869 "\n"
2870 "       // transform unnormalized eye direction into tangent space\n"
2871 "#ifdef USEEYEVECTOR\n"
2872 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2873 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2874 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2875 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2876 "#endif\n"
2877 "\n"
2878 "#ifdef USEFOG\n"
2879 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2880 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2881 "#endif\n"
2882 "\n"
2883 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2884 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2885 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2886 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2887 "#endif\n"
2888 "\n"
2889 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2890 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2891 "\n"
2892 "#ifdef USESHADOWMAPORTHO\n"
2893 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2894 "#endif\n"
2895 "\n"
2896 "#ifdef USEREFLECTION\n"
2897 "       ModelViewProjectionPosition = gl_Position;\n"
2898 "#endif\n"
2899 "}\n"
2900 "#endif // VERTEX_SHADER\n"
2901 "\n"
2902 "\n"
2903 "\n"
2904 "\n"
2905 "#ifdef FRAGMENT_SHADER\n"
2906 "void main\n"
2907 "(\n"
2908 "#ifdef USEDEFERREDLIGHTMAP\n"
2909 "#ifdef HLSL\n"
2910 "float2 Pixel : VPOS,\n"
2911 "#else\n"
2912 "float2 Pixel : WPOS,\n"
2913 "#endif\n"
2914 "#endif\n"
2915 "float4 gl_FrontColor : COLOR,\n"
2916 "float4 TexCoordBoth : TEXCOORD0,\n"
2917 "#ifdef USELIGHTMAP\n"
2918 "float2 TexCoordLightmap : TEXCOORD1,\n"
2919 "#endif\n"
2920 "#ifdef USEEYEVECTOR\n"
2921 "float3 EyeVector : TEXCOORD2,\n"
2922 "#endif\n"
2923 "#ifdef USEREFLECTION\n"
2924 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2925 "#endif\n"
2926 "#ifdef USEFOG\n"
2927 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2928 "#endif\n"
2929 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2930 "float3 LightVector : TEXCOORD1,\n"
2931 "#endif\n"
2932 "#ifdef MODE_LIGHTSOURCE\n"
2933 "float3 CubeVector : TEXCOORD3,\n"
2934 "#endif\n"
2935 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2936 "float4 ModelViewPosition : TEXCOORD0,\n"
2937 "#endif\n"
2938 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2939 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2940 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2941 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2942 "#endif\n"
2943 "#ifdef USESHADOWMAPORTHO\n"
2944 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2945 "#endif\n"
2946 "\n"
2947 "uniform sampler Texture_Normal : register(s0),\n"
2948 "uniform sampler Texture_Color : register(s1),\n"
2949 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2950 "uniform sampler Texture_Gloss : register(s2),\n"
2951 "#endif\n"
2952 "#ifdef USEGLOW\n"
2953 "uniform sampler Texture_Glow : register(s3),\n"
2954 "#endif\n"
2955 "#ifdef USEVERTEXTEXTUREBLEND\n"
2956 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2957 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2958 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2959 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2960 "#endif\n"
2961 "#ifdef USEGLOW\n"
2962 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2963 "#endif\n"
2964 "#endif\n"
2965 "#ifdef USECOLORMAPPING\n"
2966 "uniform sampler Texture_Pants : register(s4),\n"
2967 "uniform sampler Texture_Shirt : register(s7),\n"
2968 "#endif\n"
2969 "#ifdef USEFOG\n"
2970 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2971 "uniform sampler Texture_FogMask : register(s8),\n"
2972 "#endif\n"
2973 "#ifdef USELIGHTMAP\n"
2974 "uniform sampler Texture_Lightmap : register(s9),\n"
2975 "#endif\n"
2976 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2977 "uniform sampler Texture_Deluxemap : register(s10),\n"
2978 "#endif\n"
2979 "#ifdef USEREFLECTION\n"
2980 "uniform sampler Texture_Reflection : register(s7),\n"
2981 "#endif\n"
2982 "\n"
2983 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2984 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2985 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2986 "#endif\n"
2987 "#ifdef USEDEFERREDLIGHTMAP\n"
2988 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2989 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2990 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2991 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2992 "#endif\n"
2993 "\n"
2994 "#ifdef USECOLORMAPPING\n"
2995 "uniform half3 Color_Pants : register(c7),\n"
2996 "uniform half3 Color_Shirt : register(c8),\n"
2997 "#endif\n"
2998 "#ifdef USEFOG\n"
2999 "uniform float3 FogColor : register(c16),\n"
3000 "uniform float FogRangeRecip : register(c20),\n"
3001 "uniform float FogPlaneViewDist : register(c19),\n"
3002 "uniform float FogHeightFade : register(c17),\n"
3003 "#endif\n"
3004 "\n"
3005 "#ifdef USEOFFSETMAPPING\n"
3006 "uniform float OffsetMapping_Scale : register(c24),\n"
3007 "#endif\n"
3008 "\n"
3009 "#ifdef USEDEFERREDLIGHTMAP\n"
3010 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3011 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3012 "uniform half3 DeferredMod_Specular : register(c13),\n"
3013 "#endif\n"
3014 "uniform half3 Color_Ambient : register(c3),\n"
3015 "uniform half3 Color_Diffuse : register(c4),\n"
3016 "uniform half3 Color_Specular : register(c5),\n"
3017 "uniform half SpecularPower : register(c36),\n"
3018 "#ifdef USEGLOW\n"
3019 "uniform half3 Color_Glow : register(c6),\n"
3020 "#endif\n"
3021 "uniform half Alpha : register(c0),\n"
3022 "#ifdef USEREFLECTION\n"
3023 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3024 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3025 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3026 "uniform half4 ReflectColor : register(c26),\n"
3027 "#endif\n"
3028 "#ifdef USEREFLECTCUBE\n"
3029 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3030 "uniform sampler Texture_ReflectMask : register(s5),\n"
3031 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3032 "#endif\n"
3033 "#ifdef MODE_LIGHTDIRECTION\n"
3034 "uniform half3 LightColor : register(c21),\n"
3035 "#endif\n"
3036 "#ifdef MODE_LIGHTSOURCE\n"
3037 "uniform half3 LightColor : register(c21),\n"
3038 "#endif\n"
3039 "\n"
3040 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3041 "uniform sampler Texture_Attenuation : register(s9),\n"
3042 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3043 "#endif\n"
3044 "\n"
3045 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3046 "\n"
3047 "#ifdef USESHADOWMAP2D\n"
3048 "# ifdef USESHADOWSAMPLER\n"
3049 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3050 "# else\n"
3051 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3052 "# endif\n"
3053 "#endif\n"
3054 "\n"
3055 "#ifdef USESHADOWMAPVSDCT\n"
3056 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3057 "#endif\n"
3058 "\n"
3059 "#if defined(USESHADOWMAP2D)\n"
3060 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3061 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3062 "#endif\n"
3063 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3064 "\n"
3065 "out float4 gl_FragColor : COLOR\n"
3066 ")\n"
3067 "{\n"
3068 "       float2 TexCoord = TexCoordBoth.xy;\n"
3069 "#ifdef USEVERTEXTEXTUREBLEND\n"
3070 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3071 "#endif\n"
3072 "#ifdef USEOFFSETMAPPING\n"
3073 "       // apply offsetmapping\n"
3074 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3075 "#define TexCoord TexCoordOffset\n"
3076 "#endif\n"
3077 "\n"
3078 "       // combine the diffuse textures (base, pants, shirt)\n"
3079 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3080 "#ifdef USEALPHAKILL\n"
3081 "       if (color.a < 0.5)\n"
3082 "               discard;\n"
3083 "#endif\n"
3084 "       color.a *= Alpha;\n"
3085 "#ifdef USECOLORMAPPING\n"
3086 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3087 "#endif\n"
3088 "#ifdef USEVERTEXTEXTUREBLEND\n"
3089 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3090 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3091 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3092 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3093 "       color.a = 1.0;\n"
3094 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3095 "#endif\n"
3096 "\n"
3097 "       // get the surface normal\n"
3098 "#ifdef USEVERTEXTEXTUREBLEND\n"
3099 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3100 "#else\n"
3101 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3102 "#endif\n"
3103 "\n"
3104 "       // get the material colors\n"
3105 "       half3 diffusetex = color.rgb;\n"
3106 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3107 "# ifdef USEVERTEXTEXTUREBLEND\n"
3108 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3109 "# else\n"
3110 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3111 "# endif\n"
3112 "#endif\n"
3113 "\n"
3114 "#ifdef USEREFLECTCUBE\n"
3115 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3116 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3117 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3118 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3119 "#endif\n"
3120 "\n"
3121 "\n"
3122 "\n"
3123 "\n"
3124 "#ifdef MODE_LIGHTSOURCE\n"
3125 "       // light source\n"
3126 "#ifdef USEDIFFUSE\n"
3127 "       half3 lightnormal = half3(normalize(LightVector));\n"
3128 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3129 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3130 "#ifdef USESPECULAR\n"
3131 "#ifdef USEEXACTSPECULARMATH\n"
3132 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3133 "#else\n"
3134 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3135 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3136 "#endif\n"
3137 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3138 "#endif\n"
3139 "#else\n"
3140 "       color.rgb = diffusetex * Color_Ambient;\n"
3141 "#endif\n"
3142 "       color.rgb *= LightColor;\n"
3143 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3144 "#if defined(USESHADOWMAP2D)\n"
3145 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3146 "#ifdef USESHADOWMAPVSDCT\n"
3147 ", Texture_CubeProjection\n"
3148 "#endif\n"
3149 "       ));\n"
3150 "\n"
3151 "#endif\n"
3152 "# ifdef USECUBEFILTER\n"
3153 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3154 "# endif\n"
3155 "\n"
3156 "#ifdef USESHADOWMAP2D\n"
3157 "#ifdef USESHADOWMAPVSDCT\n"
3158 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3159 "#else\n"
3160 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3161 "#endif\n"
3162 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3163 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3164 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3165 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3166 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3167 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3168 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3169 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3170 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3171 "//     color.r = half(shadowmaptc.z);\n"
3172 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3173 "//     color.r = half(shadowmaptc.z);\n"
3174 "//     color.r = 1;\n"
3175 "//     color.rgb = abs(CubeVector);\n"
3176 "#endif\n"
3177 "//     color.rgb = half3(1,1,1);\n"
3178 "#endif // MODE_LIGHTSOURCE\n"
3179 "\n"
3180 "\n"
3181 "\n"
3182 "\n"
3183 "#ifdef MODE_LIGHTDIRECTION\n"
3184 "#define SHADING\n"
3185 "#ifdef USEDIFFUSE\n"
3186 "       half3 lightnormal = half3(normalize(LightVector));\n"
3187 "#endif\n"
3188 "#define lightcolor LightColor\n"
3189 "#endif // MODE_LIGHTDIRECTION\n"
3190 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3191 "#define SHADING\n"
3192 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3193 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3194 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3195 "       // convert modelspace light vector to tangentspace\n"
3196 "       half3 lightnormal;\n"
3197 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3198 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3199 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3200 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3201 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3202 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3203 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3204 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3205 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3206 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3207 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3208 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3209 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3210 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3211 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3212 "#define SHADING\n"
3213 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3214 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3215 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3216 "#endif\n"
3217 "\n"
3218 "\n"
3219 "\n"
3220 "\n"
3221 "#ifdef MODE_FAKELIGHT\n"
3222 "#define SHADING\n"
3223 "half3 lightnormal = half3(normalize(EyeVector));\n"
3224 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3225 "#endif // MODE_FAKELIGHT\n"
3226 "\n"
3227 "\n"
3228 "\n"
3229 "\n"
3230 "#ifdef MODE_LIGHTMAP\n"
3231 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3232 "#endif // MODE_LIGHTMAP\n"
3233 "#ifdef MODE_VERTEXCOLOR\n"
3234 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3235 "#endif // MODE_VERTEXCOLOR\n"
3236 "#ifdef MODE_FLATCOLOR\n"
3237 "       color.rgb = diffusetex * Color_Ambient;\n"
3238 "#endif // MODE_FLATCOLOR\n"
3239 "\n"
3240 "\n"
3241 "\n"
3242 "\n"
3243 "#ifdef SHADING\n"
3244 "# ifdef USEDIFFUSE\n"
3245 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3246 "#  ifdef USESPECULAR\n"
3247 "#   ifdef USEEXACTSPECULARMATH\n"
3248 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3249 "#   else\n"
3250 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3251 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3252 "#   endif\n"
3253 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3254 "#  else\n"
3255 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3256 "#  endif\n"
3257 "# else\n"
3258 "       color.rgb = diffusetex * Color_Ambient;\n"
3259 "# endif\n"
3260 "#endif\n"
3261 "\n"
3262 "#ifdef USESHADOWMAPORTHO\n"
3263 "       color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3264 "#endif\n"
3265 "\n"
3266 "#ifdef USEDEFERREDLIGHTMAP\n"
3267 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3268 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3269 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3270 "//     color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3271 "//     color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3272 "#endif\n"
3273 "\n"
3274 "#ifdef USEGLOW\n"
3275 "#ifdef USEVERTEXTEXTUREBLEND\n"
3276 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3277 "#else\n"
3278 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3279 "#endif\n"
3280 "#endif\n"
3281 "\n"
3282 "#ifdef USEFOG\n"
3283 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3284 "#endif\n"
3285 "\n"
3286 "       // 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"
3287 "#ifdef USEREFLECTION\n"
3288 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3289 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3290 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3291 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3292 "       // FIXME temporary hack to detect the case that the reflection\n"
3293 "       // gets blackened at edges due to leaving the area that contains actual\n"
3294 "       // content.\n"
3295 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3296 "       // 'appening.\n"
3297 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3298 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3299 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3300 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3301 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3302 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3303 "#endif\n"
3304 "\n"
3305 "       gl_FragColor = float4(color);\n"
3306 "}\n"
3307 "#endif // FRAGMENT_SHADER\n"
3308 "\n"
3309 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3310 "#endif // !MODE_DEFERREDGEOMETRY\n"
3311 "#endif // !MODE_WATER\n"
3312 "#endif // !MODE_REFRACTION\n"
3313 "#endif // !MODE_BLOOMBLUR\n"
3314 "#endif // !MODE_GENERIC\n"
3315 "#endif // !MODE_POSTPROCESS\n"
3316 "#endif // !MODE_SHOWDEPTH\n"
3317 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3318 ;
3319
3320 char *glslshaderstring = NULL;
3321 char *cgshaderstring = NULL;
3322 char *hlslshaderstring = NULL;
3323
3324 //=======================================================================================================================================================
3325
3326 typedef struct shaderpermutationinfo_s
3327 {
3328         const char *pretext;
3329         const char *name;
3330 }
3331 shaderpermutationinfo_t;
3332
3333 typedef struct shadermodeinfo_s
3334 {
3335         const char *vertexfilename;
3336         const char *geometryfilename;
3337         const char *fragmentfilename;
3338         const char *pretext;
3339         const char *name;
3340 }
3341 shadermodeinfo_t;
3342
3343 typedef enum shaderpermutation_e
3344 {
3345         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3346         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3347         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only), use vertex colors (generic only)
3348         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3349         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3350         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3351         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3352         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3353         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3354         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3355         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3356         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3357         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3358         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3359         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3360         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3361         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3362         SHADERPERMUTATION_SHADOWMAP2D = 1<<17, ///< (lightsource) use shadowmap texture as light filter
3363         SHADERPERMUTATION_SHADOWMAPPCF = 1<<18, ///< (lightsource) use percentage closer filtering on shadowmap test results
3364         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<19, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3365         SHADERPERMUTATION_SHADOWSAMPLER = 1<<20, ///< (lightsource) use hardware shadowmap test
3366         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<21, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3367         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<22, //< (lightsource) use orthographic shadowmap projection
3368         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<23, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3369         SHADERPERMUTATION_ALPHAKILL = 1<<24, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3370         SHADERPERMUTATION_REFLECTCUBE = 1<<25, ///< fake reflections using global cubemap (not HDRI light probe)
3371         SHADERPERMUTATION_NORMALMAPSCROLLBLEND = 1<<26, // (water) counter-direction normalmaps scrolling
3372         SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array
3373         SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3374 }
3375 shaderpermutation_t;
3376
3377 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3378 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3379 {
3380         {"#define USEDIFFUSE\n", " diffuse"},
3381         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3382         {"#define USEVIEWTINT\n", " viewtint"},
3383         {"#define USECOLORMAPPING\n", " colormapping"},
3384         {"#define USESATURATION\n", " saturation"},
3385         {"#define USEFOGINSIDE\n", " foginside"},
3386         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3387         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3388         {"#define USEGAMMARAMPS\n", " gammaramps"},
3389         {"#define USECUBEFILTER\n", " cubefilter"},
3390         {"#define USEGLOW\n", " glow"},
3391         {"#define USEBLOOM\n", " bloom"},
3392         {"#define USESPECULAR\n", " specular"},
3393         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3394         {"#define USEREFLECTION\n", " reflection"},
3395         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3396         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3397         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3398         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3399         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3400         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3401         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3402         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3403         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3404         {"#define USEALPHAKILL\n", " alphakill"},
3405         {"#define USEREFLECTCUBE\n", " reflectcube"},
3406         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3407 };
3408
3409 // this enum selects which of the glslshadermodeinfo entries should be used
3410 typedef enum shadermode_e
3411 {
3412         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3413         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3414         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3415         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3416         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3417         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3418         SHADERMODE_FAKELIGHT, ///< (fakelight) modulate texture by "fake" lighting (no lightmaps, no nothing)
3419         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3420         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3421         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3422         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3423         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3424         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3425         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3426         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3427         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3428         SHADERMODE_COUNT
3429 }
3430 shadermode_t;
3431
3432 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3433 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3434 {
3435         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3436         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3437         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3438         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3439         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3440         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3441         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3442         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3443         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3444         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3445         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3446         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3447         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3448         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3449         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3450         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3451 };
3452
3453 #ifdef SUPPORTCG
3454 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3455 {
3456         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3457         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3458         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3459         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3460         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3461         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3462         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
3463         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3464         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3465         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3466         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3467         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3468         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3469         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3470         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3471         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3472 };
3473 #endif
3474
3475 #ifdef SUPPORTD3D
3476 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3477 {
3478         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3479         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3480         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3481         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3482         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3483         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3484         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3485         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3486         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3487         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3488         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3489         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3490         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3491         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3492         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3493         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3494 };
3495 #endif
3496
3497 struct r_glsl_permutation_s;
3498 typedef struct r_glsl_permutation_s
3499 {
3500         /// hash lookup data
3501         struct r_glsl_permutation_s *hashnext;
3502         unsigned int mode;
3503         unsigned int permutation;
3504
3505         /// indicates if we have tried compiling this permutation already
3506         qboolean compiled;
3507         /// 0 if compilation failed
3508         int program;
3509         /// locations of detected uniforms in program object, or -1 if not found
3510         int loc_Texture_First;
3511         int loc_Texture_Second;
3512         int loc_Texture_GammaRamps;
3513         int loc_Texture_Normal;
3514         int loc_Texture_Color;
3515         int loc_Texture_Gloss;
3516         int loc_Texture_Glow;
3517         int loc_Texture_SecondaryNormal;
3518         int loc_Texture_SecondaryColor;
3519         int loc_Texture_SecondaryGloss;
3520         int loc_Texture_SecondaryGlow;
3521         int loc_Texture_Pants;
3522         int loc_Texture_Shirt;
3523         int loc_Texture_FogHeightTexture;
3524         int loc_Texture_FogMask;
3525         int loc_Texture_Lightmap;
3526         int loc_Texture_Deluxemap;
3527         int loc_Texture_Attenuation;
3528         int loc_Texture_Cube;
3529         int loc_Texture_Refraction;
3530         int loc_Texture_Reflection;
3531         int loc_Texture_ShadowMap2D;
3532         int loc_Texture_CubeProjection;
3533         int loc_Texture_ScreenDepth;
3534         int loc_Texture_ScreenNormalMap;
3535         int loc_Texture_ScreenDiffuse;
3536         int loc_Texture_ScreenSpecular;
3537         int loc_Texture_ReflectMask;
3538         int loc_Texture_ReflectCube;
3539         int loc_Alpha;
3540         int loc_BloomBlur_Parameters;
3541         int loc_ClientTime;
3542         int loc_Color_Ambient;
3543         int loc_Color_Diffuse;
3544         int loc_Color_Specular;
3545         int loc_Color_Glow;
3546         int loc_Color_Pants;
3547         int loc_Color_Shirt;
3548         int loc_DeferredColor_Ambient;
3549         int loc_DeferredColor_Diffuse;
3550         int loc_DeferredColor_Specular;
3551         int loc_DeferredMod_Diffuse;
3552         int loc_DeferredMod_Specular;
3553         int loc_DistortScaleRefractReflect;
3554         int loc_EyePosition;
3555         int loc_FogColor;
3556         int loc_FogHeightFade;
3557         int loc_FogPlane;
3558         int loc_FogPlaneViewDist;
3559         int loc_FogRangeRecip;
3560         int loc_LightColor;
3561         int loc_LightDir;
3562         int loc_LightPosition;
3563         int loc_OffsetMapping_Scale;
3564         int loc_PixelSize;
3565         int loc_ReflectColor;
3566         int loc_ReflectFactor;
3567         int loc_ReflectOffset;
3568         int loc_RefractColor;
3569         int loc_Saturation;
3570         int loc_ScreenCenterRefractReflect;
3571         int loc_ScreenScaleRefractReflect;
3572         int loc_ScreenToDepth;
3573         int loc_ShadowMap_Parameters;
3574         int loc_ShadowMap_TextureScale;
3575         int loc_SpecularPower;
3576         int loc_UserVec1;
3577         int loc_UserVec2;
3578         int loc_UserVec3;
3579         int loc_UserVec4;
3580         int loc_ViewTintColor;
3581         int loc_ViewToLight;
3582         int loc_ModelToLight;
3583         int loc_TexMatrix;
3584         int loc_BackgroundTexMatrix;
3585         int loc_ModelViewProjectionMatrix;
3586         int loc_ModelViewMatrix;
3587         int loc_PixelToScreenTexCoord;
3588         int loc_ModelToReflectCube;
3589         int loc_ShadowMapMatrix;
3590         int loc_BloomColorSubtract;
3591         int loc_NormalmapScrollBlend;
3592 }
3593 r_glsl_permutation_t;
3594
3595 #define SHADERPERMUTATION_HASHSIZE 256
3596
3597
3598 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3599 // these can NOT degrade! only use for simple stuff
3600 enum
3601 {
3602         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3603         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3604         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3605         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3606         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3607         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
3608 };
3609 #define SHADERSTATICPARMS_COUNT 6
3610
3611 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3612 static int shaderstaticparms_count = 0;
3613
3614 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3615 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3616 qboolean R_CompileShader_CheckStaticParms(void)
3617 {
3618         static int r_compileshader_staticparms_save[1];
3619         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3620         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3621
3622         // detect all
3623         if (r_glsl_saturation_redcompensate.integer)
3624                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3625         if (r_shadow_glossexact.integer)
3626                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3627         if (r_glsl_postprocess.integer)
3628         {
3629                 if (r_glsl_postprocess_uservec1_enable.integer)
3630                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3631                 if (r_glsl_postprocess_uservec2_enable.integer)
3632                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3633                 if (r_glsl_postprocess_uservec3_enable.integer)
3634                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3635                 if (r_glsl_postprocess_uservec4_enable.integer)
3636                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3637         }
3638         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3639 }
3640
3641 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3642         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3643                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3644         else \
3645                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3646 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3647 {
3648         shaderstaticparms_count = 0;
3649
3650         // emit all
3651         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3652         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3653         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3654         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3655         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3656         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3657 }
3658
3659 /// information about each possible shader permutation
3660 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3661 /// currently selected permutation
3662 r_glsl_permutation_t *r_glsl_permutation;
3663 /// storage for permutations linked in the hash table
3664 memexpandablearray_t r_glsl_permutationarray;
3665
3666 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3667 {
3668         //unsigned int hashdepth = 0;
3669         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3670         r_glsl_permutation_t *p;
3671         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3672         {
3673                 if (p->mode == mode && p->permutation == permutation)
3674                 {
3675                         //if (hashdepth > 10)
3676                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3677                         return p;
3678                 }
3679                 //hashdepth++;
3680         }
3681         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3682         p->mode = mode;
3683         p->permutation = permutation;
3684         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3685         r_glsl_permutationhash[mode][hashindex] = p;
3686         //if (hashdepth > 10)
3687         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3688         return p;
3689 }
3690
3691 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3692 {
3693         char *shaderstring;
3694         if (!filename || !filename[0])
3695                 return NULL;
3696         if (!strcmp(filename, "glsl/default.glsl"))
3697         {
3698                 if (!glslshaderstring)
3699                 {
3700                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3701                         if (glslshaderstring)
3702                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3703                         else
3704                                 glslshaderstring = (char *)builtinshaderstring;
3705                 }
3706                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3707                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3708                 return shaderstring;
3709         }
3710         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3711         if (shaderstring)
3712         {
3713                 if (printfromdisknotice)
3714                         Con_DPrintf("from disk %s... ", filename);
3715                 return shaderstring;
3716         }
3717         return shaderstring;
3718 }
3719
3720 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3721 {
3722         int i;
3723         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3724         char *vertexstring, *geometrystring, *fragmentstring;
3725         char permutationname[256];
3726         int vertstrings_count = 0;
3727         int geomstrings_count = 0;
3728         int fragstrings_count = 0;
3729         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3730         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3731         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3732
3733         if (p->compiled)
3734                 return;
3735         p->compiled = true;
3736         p->program = 0;
3737
3738         permutationname[0] = 0;
3739         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3740         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3741         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3742
3743         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3744
3745         // the first pretext is which type of shader to compile as
3746         // (later these will all be bound together as a program object)
3747         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3748         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3749         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3750
3751         // the second pretext is the mode (for example a light source)
3752         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3753         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3754         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3755         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3756
3757         // now add all the permutation pretexts
3758         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3759         {
3760                 if (permutation & (1<<i))
3761                 {
3762                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3763                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3764                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3765                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3766                 }
3767                 else
3768                 {
3769                         // keep line numbers correct
3770                         vertstrings_list[vertstrings_count++] = "\n";
3771                         geomstrings_list[geomstrings_count++] = "\n";
3772                         fragstrings_list[fragstrings_count++] = "\n";
3773                 }
3774         }
3775
3776         // add static parms
3777         R_CompileShader_AddStaticParms(mode, permutation);
3778         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3779         vertstrings_count += shaderstaticparms_count;
3780         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3781         geomstrings_count += shaderstaticparms_count;
3782         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3783         fragstrings_count += shaderstaticparms_count;
3784
3785         // now append the shader text itself
3786         vertstrings_list[vertstrings_count++] = vertexstring;
3787         geomstrings_list[geomstrings_count++] = geometrystring;
3788         fragstrings_list[fragstrings_count++] = fragmentstring;
3789
3790         // if any sources were NULL, clear the respective list
3791         if (!vertexstring)
3792                 vertstrings_count = 0;
3793         if (!geometrystring)
3794                 geomstrings_count = 0;
3795         if (!fragmentstring)
3796                 fragstrings_count = 0;
3797
3798         // compile the shader program
3799         if (vertstrings_count + geomstrings_count + fragstrings_count)
3800                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3801         if (p->program)
3802         {
3803                 CHECKGLERROR
3804                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3805                 // look up all the uniform variable names we care about, so we don't
3806                 // have to look them up every time we set them
3807
3808                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3809                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3810                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3811                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3812                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3813                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3814                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3815                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3816                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3817                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3818                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3819                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3820                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3821                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3822                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3823                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3824                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3825                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3826                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3827                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3828                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3829                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3830                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3831                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3832                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3833                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3834                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3835                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3836                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3837                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3838                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3839                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3840                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3841                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3842                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3843                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3844                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3845                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3846                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3847                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3848                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3849                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3850                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3851                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3852                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3853                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3854                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3855                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3856                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3857                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3858                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3859                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3860                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3861                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3862                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3863                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3864                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3865                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3866                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3867                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3868                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3869                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3870                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3871                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3872                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3873                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3874                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3875                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3876                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3877                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3878                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3879                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3880                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3881                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3882                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3883                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3884                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3885                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3886                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3887                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3888                 p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3889                 p->loc_NormalmapScrollBlend       = qglGetUniformLocationARB(p->program, "NormalmapScrollBlend");
3890                 // initialize the samplers to refer to the texture units we use
3891                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3892                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3893                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3894                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3895                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3896                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3897                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3898                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3899                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3900                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3901                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3902                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3903                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3904                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3905                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3906                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3907                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3908                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3909                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3910                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3911                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3912                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3913                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3914                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3915                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3916                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3917                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3918                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3919                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3920                 CHECKGLERROR
3921                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3922         }
3923         else
3924                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3925
3926         // free the strings
3927         if (vertexstring)
3928                 Mem_Free(vertexstring);
3929         if (geometrystring)
3930                 Mem_Free(geometrystring);
3931         if (fragmentstring)
3932                 Mem_Free(fragmentstring);
3933 }
3934
3935 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3936 {
3937         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3938         if (r_glsl_permutation != perm)
3939         {
3940                 r_glsl_permutation = perm;
3941                 if (!r_glsl_permutation->program)
3942                 {
3943                         if (!r_glsl_permutation->compiled)
3944                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3945                         if (!r_glsl_permutation->program)
3946                         {
3947                                 // remove features until we find a valid permutation
3948                                 int i;
3949                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3950                                 {
3951                                         // reduce i more quickly whenever it would not remove any bits
3952                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3953                                         if (!(permutation & j))
3954                                                 continue;
3955                                         permutation -= j;
3956                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3957                                         if (!r_glsl_permutation->compiled)
3958                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3959                                         if (r_glsl_permutation->program)
3960                                                 break;
3961                                 }
3962                                 if (i >= SHADERPERMUTATION_COUNT)
3963                                 {
3964                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3965                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3966                                         qglUseProgramObjectARB(0);CHECKGLERROR
3967                                         return; // no bit left to clear, entire mode is broken
3968                                 }
3969                         }
3970                 }
3971                 CHECKGLERROR
3972                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3973         }
3974         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3975         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3976         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3977 }
3978
3979 #ifdef SUPPORTCG
3980 #include <Cg/cgGL.h>
3981 struct r_cg_permutation_s;
3982 typedef struct r_cg_permutation_s
3983 {
3984         /// hash lookup data
3985         struct r_cg_permutation_s *hashnext;
3986         unsigned int mode;
3987         unsigned int permutation;
3988
3989         /// indicates if we have tried compiling this permutation already
3990         qboolean compiled;
3991         /// 0 if compilation failed
3992         CGprogram vprogram;
3993         CGprogram fprogram;
3994         /// locations of detected parameters in programs, or NULL if not found
3995         CGparameter vp_EyePosition;
3996         CGparameter vp_FogPlane;
3997         CGparameter vp_LightDir;
3998         CGparameter vp_LightPosition;
3999         CGparameter vp_ModelToLight;
4000         CGparameter vp_TexMatrix;
4001         CGparameter vp_BackgroundTexMatrix;
4002         CGparameter vp_ModelViewProjectionMatrix;
4003         CGparameter vp_ModelViewMatrix;
4004         CGparameter vp_ShadowMapMatrix;
4005
4006         CGparameter fp_Texture_First;
4007         CGparameter fp_Texture_Second;
4008         CGparameter fp_Texture_GammaRamps;
4009         CGparameter fp_Texture_Normal;
4010         CGparameter fp_Texture_Color;
4011         CGparameter fp_Texture_Gloss;
4012         CGparameter fp_Texture_Glow;
4013         CGparameter fp_Texture_SecondaryNormal;
4014         CGparameter fp_Texture_SecondaryColor;
4015         CGparameter fp_Texture_SecondaryGloss;
4016         CGparameter fp_Texture_SecondaryGlow;
4017         CGparameter fp_Texture_Pants;
4018         CGparameter fp_Texture_Shirt;
4019         CGparameter fp_Texture_FogHeightTexture;
4020         CGparameter fp_Texture_FogMask;
4021         CGparameter fp_Texture_Lightmap;
4022         CGparameter fp_Texture_Deluxemap;
4023         CGparameter fp_Texture_Attenuation;
4024         CGparameter fp_Texture_Cube;
4025         CGparameter fp_Texture_Refraction;
4026         CGparameter fp_Texture_Reflection;
4027         CGparameter fp_Texture_ShadowMap2D;
4028         CGparameter fp_Texture_CubeProjection;
4029         CGparameter fp_Texture_ScreenDepth;
4030         CGparameter fp_Texture_ScreenNormalMap;
4031         CGparameter fp_Texture_ScreenDiffuse;
4032         CGparameter fp_Texture_ScreenSpecular;
4033         CGparameter fp_Texture_ReflectMask;
4034         CGparameter fp_Texture_ReflectCube;
4035         CGparameter fp_Alpha;
4036         CGparameter fp_BloomBlur_Parameters;
4037         CGparameter fp_ClientTime;
4038         CGparameter fp_Color_Ambient;
4039         CGparameter fp_Color_Diffuse;
4040         CGparameter fp_Color_Specular;
4041         CGparameter fp_Color_Glow;
4042         CGparameter fp_Color_Pants;
4043         CGparameter fp_Color_Shirt;
4044         CGparameter fp_DeferredColor_Ambient;
4045         CGparameter fp_DeferredColor_Diffuse;
4046         CGparameter fp_DeferredColor_Specular;
4047         CGparameter fp_DeferredMod_Diffuse;
4048         CGparameter fp_DeferredMod_Specular;
4049         CGparameter fp_DistortScaleRefractReflect;
4050         CGparameter fp_EyePosition;
4051         CGparameter fp_FogColor;
4052         CGparameter fp_FogHeightFade;
4053         CGparameter fp_FogPlane;
4054         CGparameter fp_FogPlaneViewDist;
4055         CGparameter fp_FogRangeRecip;
4056         CGparameter fp_LightColor;
4057         CGparameter fp_LightDir;
4058         CGparameter fp_LightPosition;
4059         CGparameter fp_OffsetMapping_Scale;
4060         CGparameter fp_PixelSize;
4061         CGparameter fp_ReflectColor;
4062         CGparameter fp_ReflectFactor;
4063         CGparameter fp_ReflectOffset;
4064         CGparameter fp_RefractColor;
4065         CGparameter fp_Saturation;
4066         CGparameter fp_ScreenCenterRefractReflect;
4067         CGparameter fp_ScreenScaleRefractReflect;
4068         CGparameter fp_ScreenToDepth;
4069         CGparameter fp_ShadowMap_Parameters;
4070         CGparameter fp_ShadowMap_TextureScale;
4071         CGparameter fp_SpecularPower;
4072         CGparameter fp_UserVec1;
4073         CGparameter fp_UserVec2;
4074         CGparameter fp_UserVec3;
4075         CGparameter fp_UserVec4;
4076         CGparameter fp_ViewTintColor;
4077         CGparameter fp_ViewToLight;
4078         CGparameter fp_PixelToScreenTexCoord;
4079         CGparameter fp_ModelToReflectCube;
4080         CGparameter fp_BloomColorSubtract;
4081         CGparameter fp_NormalmapScrollBlend;
4082 }
4083 r_cg_permutation_t;
4084
4085 /// information about each possible shader permutation
4086 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4087 /// currently selected permutation
4088 r_cg_permutation_t *r_cg_permutation;
4089 /// storage for permutations linked in the hash table
4090 memexpandablearray_t r_cg_permutationarray;
4091
4092 #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));}}
4093
4094 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4095 {
4096         //unsigned int hashdepth = 0;
4097         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4098         r_cg_permutation_t *p;
4099         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4100         {
4101                 if (p->mode == mode && p->permutation == permutation)
4102                 {
4103                         //if (hashdepth > 10)
4104                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4105                         return p;
4106                 }
4107                 //hashdepth++;
4108         }
4109         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4110         p->mode = mode;
4111         p->permutation = permutation;
4112         p->hashnext = r_cg_permutationhash[mode][hashindex];
4113         r_cg_permutationhash[mode][hashindex] = p;
4114         //if (hashdepth > 10)
4115         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4116         return p;
4117 }
4118
4119 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4120 {
4121         char *shaderstring;
4122         if (!filename || !filename[0])
4123                 return NULL;
4124         if (!strcmp(filename, "cg/default.cg"))
4125         {
4126                 if (!cgshaderstring)
4127                 {
4128                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4129                         if (cgshaderstring)
4130                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4131                         else
4132                                 cgshaderstring = (char *)builtincgshaderstring;
4133                 }
4134                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4135                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4136                 return shaderstring;
4137         }
4138         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4139         if (shaderstring)
4140         {
4141                 if (printfromdisknotice)
4142                         Con_DPrintf("from disk %s... ", filename);
4143                 return shaderstring;
4144         }
4145         return shaderstring;
4146 }
4147
4148 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4149 {
4150         // TODO: load or create .fp and .vp shader files
4151 }
4152
4153 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4154 {
4155         int i;
4156         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4157         int vertstring_length = 0;
4158         int geomstring_length = 0;
4159         int fragstring_length = 0;
4160         char *t;
4161         char *vertexstring, *geometrystring, *fragmentstring;
4162         char *vertstring, *geomstring, *fragstring;
4163         char permutationname[256];
4164         char cachename[256];
4165         CGprofile vertexProfile;
4166         CGprofile fragmentProfile;
4167         int vertstrings_count = 0;
4168         int geomstrings_count = 0;
4169         int fragstrings_count = 0;
4170         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4171         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4172         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4173
4174         if (p->compiled)
4175                 return;
4176         p->compiled = true;
4177         p->vprogram = NULL;
4178         p->fprogram = NULL;
4179
4180         permutationname[0] = 0;
4181         cachename[0] = 0;
4182         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4183         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4184         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4185
4186         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4187         strlcat(cachename, "cg/", sizeof(cachename));
4188
4189         // the first pretext is which type of shader to compile as
4190         // (later these will all be bound together as a program object)
4191         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4192         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4193         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4194
4195         // the second pretext is the mode (for example a light source)
4196         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4197         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4198         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4199         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4200         strlcat(cachename, modeinfo->name, sizeof(cachename));
4201
4202         // now add all the permutation pretexts
4203         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4204         {
4205                 if (permutation & (1<<i))
4206                 {
4207                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4208                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4209                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4210                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4211                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4212                 }
4213                 else
4214                 {
4215                         // keep line numbers correct
4216                         vertstrings_list[vertstrings_count++] = "\n";
4217                         geomstrings_list[geomstrings_count++] = "\n";
4218                         fragstrings_list[fragstrings_count++] = "\n";
4219                 }
4220         }
4221
4222         // add static parms
4223         R_CompileShader_AddStaticParms(mode, permutation);
4224         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4225         vertstrings_count += shaderstaticparms_count;
4226         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4227         geomstrings_count += shaderstaticparms_count;
4228         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4229         fragstrings_count += shaderstaticparms_count;
4230
4231         // replace spaces in the cachename with _ characters
4232         for (i = 0;cachename[i];i++)
4233                 if (cachename[i] == ' ')
4234                         cachename[i] = '_';
4235
4236         // now append the shader text itself
4237         vertstrings_list[vertstrings_count++] = vertexstring;
4238         geomstrings_list[geomstrings_count++] = geometrystring;
4239         fragstrings_list[fragstrings_count++] = fragmentstring;
4240
4241         // if any sources were NULL, clear the respective list
4242         if (!vertexstring)
4243                 vertstrings_count = 0;
4244         if (!geometrystring)
4245                 geomstrings_count = 0;
4246         if (!fragmentstring)
4247                 fragstrings_count = 0;
4248
4249         vertstring_length = 0;
4250         for (i = 0;i < vertstrings_count;i++)
4251                 vertstring_length += strlen(vertstrings_list[i]);
4252         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4253         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4254                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4255
4256         geomstring_length = 0;
4257         for (i = 0;i < geomstrings_count;i++)
4258                 geomstring_length += strlen(geomstrings_list[i]);
4259         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4260         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4261                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4262
4263         fragstring_length = 0;
4264         for (i = 0;i < fragstrings_count;i++)
4265                 fragstring_length += strlen(fragstrings_list[i]);
4266         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4267         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4268                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4269
4270         CHECKGLERROR
4271         CHECKCGERROR
4272         //vertexProfile = CG_PROFILE_ARBVP1;
4273         //fragmentProfile = CG_PROFILE_ARBFP1;
4274         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4275         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4276         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4277         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4278         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4279         CHECKGLERROR
4280
4281         // try to load the cached shader, or generate one
4282         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4283
4284         // if caching failed, do a dynamic compile for now
4285         CHECKCGERROR
4286         if (vertstring[0] && !p->vprogram)
4287                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4288         CHECKCGERROR
4289         if (fragstring[0] && !p->fprogram)
4290                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4291         CHECKCGERROR
4292
4293         // look up all the uniform variable names we care about, so we don't
4294         // have to look them up every time we set them
4295         if (p->vprogram)
4296         {
4297                 CHECKCGERROR
4298                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4299                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4300                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4301                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4302                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4303                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4304                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4305                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4306                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4307                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4308                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4309                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4310                 CHECKCGERROR
4311         }
4312         if (p->fprogram)
4313         {
4314                 CHECKCGERROR
4315                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4316                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4317                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4318                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4319                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4320                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4321                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4322                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4323                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4324                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4325                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4326                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4327                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4328                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4329                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4330                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4331                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4332                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4333                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4334                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4335                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4336                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4337                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4338                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4339                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4340                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4341                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4342                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4343                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4344                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4345                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4346                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4347                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4348                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4349                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4350                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4351                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4352                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4353                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4354                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4355                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4356                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4357                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4358                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4359                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4360                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4361                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4362                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4363                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4364                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4365                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4366                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4367                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4368                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4369                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4370                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4371                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4372                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4373                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4374                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4375                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4376                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4377                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4378                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4379                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4380                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4381                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4382                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4383                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4384                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4385                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4386                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4387                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4388                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4389                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4390                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4391                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4392                 p->fp_NormalmapScrollBlend       = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4393                 CHECKCGERROR
4394         }
4395
4396         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4397                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4398         else
4399                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4400
4401         // free the strings
4402         if (vertstring)
4403                 Mem_Free(vertstring);
4404         if (geomstring)
4405                 Mem_Free(geomstring);
4406         if (fragstring)
4407                 Mem_Free(fragstring);
4408         if (vertexstring)
4409                 Mem_Free(vertexstring);
4410         if (geometrystring)
4411                 Mem_Free(geometrystring);
4412         if (fragmentstring)
4413                 Mem_Free(fragmentstring);
4414 }
4415
4416 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4417 {
4418         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4419         CHECKGLERROR
4420         CHECKCGERROR
4421         if (r_cg_permutation != perm)
4422         {
4423                 r_cg_permutation = perm;
4424                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4425                 {
4426                         if (!r_cg_permutation->compiled)
4427                                 R_CG_CompilePermutation(perm, mode, permutation);
4428                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4429                         {
4430                                 // remove features until we find a valid permutation
4431                                 int i;
4432                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4433                                 {
4434                                         // reduce i more quickly whenever it would not remove any bits
4435                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4436                                         if (!(permutation & j))
4437                                                 continue;
4438                                         permutation -= j;
4439                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4440                                         if (!r_cg_permutation->compiled)
4441                                                 R_CG_CompilePermutation(perm, mode, permutation);
4442                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4443                                                 break;
4444                                 }
4445                                 if (i >= SHADERPERMUTATION_COUNT)
4446                                 {
4447                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4448                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4449                                         return; // no bit left to clear, entire mode is broken
4450                                 }
4451                         }
4452                 }
4453                 CHECKGLERROR
4454                 CHECKCGERROR
4455                 if (r_cg_permutation->vprogram)
4456                 {
4457                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4458                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4459                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4460                 }
4461                 else
4462                 {
4463                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4464                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4465                 }
4466                 if (r_cg_permutation->fprogram)
4467                 {
4468                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4469                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4470                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4471                 }
4472                 else
4473                 {
4474                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4475                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4476                 }
4477         }
4478         CHECKCGERROR
4479         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4480         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4481         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4482 }
4483
4484 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4485 {
4486         cgGLSetTextureParameter(param, R_GetTexture(tex));
4487         cgGLEnableTextureParameter(param);
4488 }
4489 #endif
4490
4491 #ifdef SUPPORTD3D
4492
4493 #ifdef SUPPORTD3D
4494 #include <d3d9.h>
4495 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4496 extern D3DCAPS9 vid_d3d9caps;
4497 #endif
4498
4499 struct r_hlsl_permutation_s;
4500 typedef struct r_hlsl_permutation_s
4501 {
4502         /// hash lookup data
4503         struct r_hlsl_permutation_s *hashnext;
4504         unsigned int mode;
4505         unsigned int permutation;
4506
4507         /// indicates if we have tried compiling this permutation already
4508         qboolean compiled;
4509         /// NULL if compilation failed
4510         IDirect3DVertexShader9 *vertexshader;
4511         IDirect3DPixelShader9 *pixelshader;
4512 }
4513 r_hlsl_permutation_t;
4514
4515 typedef enum D3DVSREGISTER_e
4516 {
4517         D3DVSREGISTER_TexMatrix = 0, // float4x4
4518         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4519         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4520         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4521         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4522         D3DVSREGISTER_ModelToLight = 20, // float4x4
4523         D3DVSREGISTER_EyePosition = 24,
4524         D3DVSREGISTER_FogPlane = 25,
4525         D3DVSREGISTER_LightDir = 26,
4526         D3DVSREGISTER_LightPosition = 27,
4527 }
4528 D3DVSREGISTER_t;
4529
4530 typedef enum D3DPSREGISTER_e
4531 {
4532         D3DPSREGISTER_Alpha = 0,
4533         D3DPSREGISTER_BloomBlur_Parameters = 1,
4534         D3DPSREGISTER_ClientTime = 2,
4535         D3DPSREGISTER_Color_Ambient = 3,
4536         D3DPSREGISTER_Color_Diffuse = 4,
4537         D3DPSREGISTER_Color_Specular = 5,
4538         D3DPSREGISTER_Color_Glow = 6,
4539         D3DPSREGISTER_Color_Pants = 7,
4540         D3DPSREGISTER_Color_Shirt = 8,
4541         D3DPSREGISTER_DeferredColor_Ambient = 9,
4542         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4543         D3DPSREGISTER_DeferredColor_Specular = 11,
4544         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4545         D3DPSREGISTER_DeferredMod_Specular = 13,
4546         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4547         D3DPSREGISTER_EyePosition = 15, // unused
4548         D3DPSREGISTER_FogColor = 16,
4549         D3DPSREGISTER_FogHeightFade = 17,
4550         D3DPSREGISTER_FogPlane = 18,
4551         D3DPSREGISTER_FogPlaneViewDist = 19,
4552         D3DPSREGISTER_FogRangeRecip = 20,
4553         D3DPSREGISTER_LightColor = 21,
4554         D3DPSREGISTER_LightDir = 22, // unused
4555         D3DPSREGISTER_LightPosition = 23,
4556         D3DPSREGISTER_OffsetMapping_Scale = 24,
4557         D3DPSREGISTER_PixelSize = 25,
4558         D3DPSREGISTER_ReflectColor = 26,
4559         D3DPSREGISTER_ReflectFactor = 27,
4560         D3DPSREGISTER_ReflectOffset = 28,
4561         D3DPSREGISTER_RefractColor = 29,
4562         D3DPSREGISTER_Saturation = 30,
4563         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4564         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4565         D3DPSREGISTER_ScreenToDepth = 33,
4566         D3DPSREGISTER_ShadowMap_Parameters = 34,
4567         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4568         D3DPSREGISTER_SpecularPower = 36,
4569         D3DPSREGISTER_UserVec1 = 37,
4570         D3DPSREGISTER_UserVec2 = 38,
4571         D3DPSREGISTER_UserVec3 = 39,
4572         D3DPSREGISTER_UserVec4 = 40,
4573         D3DPSREGISTER_ViewTintColor = 41,
4574         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4575         D3DPSREGISTER_BloomColorSubtract = 43,
4576         D3DPSREGISTER_ViewToLight = 44, // float4x4
4577         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4578         D3DPSREGISTER_NormalmapScrollBlend = 52,
4579         // next at 53
4580 }
4581 D3DPSREGISTER_t;
4582
4583 /// information about each possible shader permutation
4584 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4585 /// currently selected permutation
4586 r_hlsl_permutation_t *r_hlsl_permutation;
4587 /// storage for permutations linked in the hash table
4588 memexpandablearray_t r_hlsl_permutationarray;
4589
4590 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4591 {
4592         //unsigned int hashdepth = 0;
4593         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4594         r_hlsl_permutation_t *p;
4595         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4596         {
4597                 if (p->mode == mode && p->permutation == permutation)
4598                 {
4599                         //if (hashdepth > 10)
4600                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4601                         return p;
4602                 }
4603                 //hashdepth++;
4604         }
4605         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4606         p->mode = mode;
4607         p->permutation = permutation;
4608         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4609         r_hlsl_permutationhash[mode][hashindex] = p;
4610         //if (hashdepth > 10)
4611         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4612         return p;
4613 }
4614
4615 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4616 {
4617         char *shaderstring;
4618         if (!filename || !filename[0])
4619                 return NULL;
4620         if (!strcmp(filename, "hlsl/default.hlsl"))
4621         {
4622                 if (!hlslshaderstring)
4623                 {
4624                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4625                         if (hlslshaderstring)
4626                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4627                         else
4628                                 hlslshaderstring = (char *)builtincgshaderstring;
4629                 }
4630                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4631                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4632                 return shaderstring;
4633         }
4634         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4635         if (shaderstring)
4636         {
4637                 if (printfromdisknotice)
4638                         Con_DPrintf("from disk %s... ", filename);
4639                 return shaderstring;
4640         }
4641         return shaderstring;
4642 }
4643
4644 #include <d3dx9.h>
4645 //#include <d3dx9shader.h>
4646 //#include <d3dx9mesh.h>
4647
4648 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4649 {
4650         DWORD *vsbin = NULL;
4651         DWORD *psbin = NULL;
4652         fs_offset_t vsbinsize;
4653         fs_offset_t psbinsize;
4654 //      IDirect3DVertexShader9 *vs = NULL;
4655 //      IDirect3DPixelShader9 *ps = NULL;
4656         ID3DXBuffer *vslog = NULL;
4657         ID3DXBuffer *vsbuffer = NULL;
4658         ID3DXConstantTable *vsconstanttable = NULL;
4659         ID3DXBuffer *pslog = NULL;
4660         ID3DXBuffer *psbuffer = NULL;
4661         ID3DXConstantTable *psconstanttable = NULL;
4662         int vsresult = 0;
4663         int psresult = 0;
4664         char temp[MAX_INPUTLINE];
4665         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4666         qboolean debugshader = gl_paranoid.integer != 0;
4667         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4668         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4669         if (!debugshader)
4670         {
4671                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4672                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4673         }
4674         if ((!vsbin && vertstring) || (!psbin && fragstring))
4675         {
4676                 const char* dllnames_d3dx9 [] =
4677                 {
4678                         "d3dx9_43.dll",
4679                         "d3dx9_42.dll",
4680                         "d3dx9_41.dll",
4681                         "d3dx9_40.dll",
4682                         "d3dx9_39.dll",
4683                         "d3dx9_38.dll",
4684                         "d3dx9_37.dll",
4685                         "d3dx9_36.dll",
4686                         "d3dx9_35.dll",
4687                         "d3dx9_34.dll",
4688                         "d3dx9_33.dll",
4689                         "d3dx9_32.dll",
4690                         "d3dx9_31.dll",
4691                         "d3dx9_30.dll",
4692                         "d3dx9_29.dll",
4693                         "d3dx9_28.dll",
4694                         "d3dx9_27.dll",
4695                         "d3dx9_26.dll",
4696                         "d3dx9_25.dll",
4697                         "d3dx9_24.dll",
4698                         NULL
4699                 };
4700                 dllhandle_t d3dx9_dll = NULL;
4701                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4702                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4703                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4704                 dllfunction_t d3dx9_dllfuncs[] =
4705                 {
4706                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4707                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4708                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4709                         {NULL, NULL}
4710                 };
4711                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4712                 {
4713                         DWORD shaderflags = 0;
4714                         if (debugshader)
4715                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4716                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4717                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4718                         if (vertstring && vertstring[0])
4719                         {
4720                                 if (debugshader)
4721                                 {
4722 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4723 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4724                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4725                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4726                                 }
4727                                 else
4728                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4729                                 if (vsbuffer)
4730                                 {
4731                                         vsbinsize = vsbuffer->GetBufferSize();
4732                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4733                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4734                                         vsbuffer->Release();
4735                                 }
4736                                 if (vslog)
4737                                 {
4738                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4739                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4740                                         vslog->Release();
4741                                 }
4742                         }
4743                         if (fragstring && fragstring[0])
4744                         {
4745                                 if (debugshader)
4746                                 {
4747 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4748 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4749                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4750                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4751                                 }
4752                                 else
4753                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4754                                 if (psbuffer)
4755                                 {
4756                                         psbinsize = psbuffer->GetBufferSize();
4757                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4758                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4759                                         psbuffer->Release();
4760                                 }
4761                                 if (pslog)
4762                                 {
4763                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4764                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4765                                         pslog->Release();
4766                                 }
4767                         }
4768                         Sys_UnloadLibrary(&d3dx9_dll);
4769                 }
4770                 else
4771                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4772         }
4773         if (vsbin && psbin)
4774         {
4775                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4776                 if (FAILED(vsresult))
4777                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4778                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4779                 if (FAILED(psresult))
4780                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4781         }
4782         // free the shader data
4783         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4784         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4785 }
4786
4787 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4788 {
4789         int i;
4790         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4791         int vertstring_length = 0;
4792         int geomstring_length = 0;
4793         int fragstring_length = 0;
4794         char *t;
4795         char *vertexstring, *geometrystring, *fragmentstring;
4796         char *vertstring, *geomstring, *fragstring;
4797         char permutationname[256];
4798         char cachename[256];
4799         int vertstrings_count = 0;
4800         int geomstrings_count = 0;
4801         int fragstrings_count = 0;
4802         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4803         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4804         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4805
4806         if (p->compiled)
4807                 return;
4808         p->compiled = true;
4809         p->vertexshader = NULL;
4810         p->pixelshader = NULL;
4811
4812         permutationname[0] = 0;
4813         cachename[0] = 0;
4814         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4815         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4816         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4817
4818         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4819         strlcat(cachename, "hlsl/", sizeof(cachename));
4820
4821         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4822         vertstrings_count = 0;
4823         geomstrings_count = 0;
4824         fragstrings_count = 0;
4825         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4826         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4827         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4828
4829         // the first pretext is which type of shader to compile as
4830         // (later these will all be bound together as a program object)
4831         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4832         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4833         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4834
4835         // the second pretext is the mode (for example a light source)
4836         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4837         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4838         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4839         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4840         strlcat(cachename, modeinfo->name, sizeof(cachename));
4841
4842         // now add all the permutation pretexts
4843         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4844         {
4845                 if (permutation & (1<<i))
4846                 {
4847                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4848                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4849                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4850                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4851                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4852                 }
4853                 else
4854                 {
4855                         // keep line numbers correct
4856                         vertstrings_list[vertstrings_count++] = "\n";
4857                         geomstrings_list[geomstrings_count++] = "\n";
4858                         fragstrings_list[fragstrings_count++] = "\n";
4859                 }
4860         }
4861
4862         // add static parms
4863         R_CompileShader_AddStaticParms(mode, permutation);
4864         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4865         vertstrings_count += shaderstaticparms_count;
4866         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4867         geomstrings_count += shaderstaticparms_count;
4868         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4869         fragstrings_count += shaderstaticparms_count;
4870
4871         // replace spaces in the cachename with _ characters
4872         for (i = 0;cachename[i];i++)
4873                 if (cachename[i] == ' ')
4874                         cachename[i] = '_';
4875
4876         // now append the shader text itself
4877         vertstrings_list[vertstrings_count++] = vertexstring;
4878         geomstrings_list[geomstrings_count++] = geometrystring;
4879         fragstrings_list[fragstrings_count++] = fragmentstring;
4880
4881         // if any sources were NULL, clear the respective list
4882         if (!vertexstring)
4883                 vertstrings_count = 0;
4884         if (!geometrystring)
4885                 geomstrings_count = 0;
4886         if (!fragmentstring)
4887                 fragstrings_count = 0;
4888
4889         vertstring_length = 0;
4890         for (i = 0;i < vertstrings_count;i++)
4891                 vertstring_length += strlen(vertstrings_list[i]);
4892         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4893         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4894                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4895
4896         geomstring_length = 0;
4897         for (i = 0;i < geomstrings_count;i++)
4898                 geomstring_length += strlen(geomstrings_list[i]);
4899         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4900         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4901                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4902
4903         fragstring_length = 0;
4904         for (i = 0;i < fragstrings_count;i++)
4905                 fragstring_length += strlen(fragstrings_list[i]);
4906         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4907         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4908                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4909
4910         // try to load the cached shader, or generate one
4911         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4912
4913         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4914                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4915         else
4916                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4917
4918         // free the strings
4919         if (vertstring)
4920                 Mem_Free(vertstring);
4921         if (geomstring)
4922                 Mem_Free(geomstring);
4923         if (fragstring)
4924                 Mem_Free(fragstring);
4925         if (vertexstring)
4926                 Mem_Free(vertexstring);
4927         if (geometrystring)
4928                 Mem_Free(geometrystring);
4929         if (fragmentstring)
4930                 Mem_Free(fragmentstring);
4931 }
4932
4933 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4934 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4935 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);}
4936 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);}
4937 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);}
4938 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);}
4939
4940 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4941 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4942 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);}
4943 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);}
4944 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);}
4945 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);}
4946
4947 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4948 {
4949         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4950         if (r_hlsl_permutation != perm)
4951         {
4952                 r_hlsl_permutation = perm;
4953                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4954                 {
4955                         if (!r_hlsl_permutation->compiled)
4956                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4957                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4958                         {
4959                                 // remove features until we find a valid permutation
4960                                 int i;
4961                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4962                                 {
4963                                         // reduce i more quickly whenever it would not remove any bits
4964                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4965                                         if (!(permutation & j))
4966                                                 continue;
4967                                         permutation -= j;
4968                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4969                                         if (!r_hlsl_permutation->compiled)
4970                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4971                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4972                                                 break;
4973                                 }
4974                                 if (i >= SHADERPERMUTATION_COUNT)
4975                                 {
4976                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4977                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4978                                         return; // no bit left to clear, entire mode is broken
4979                                 }
4980                         }
4981                 }
4982                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4983                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4984         }
4985         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4986         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4987         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4988 }
4989 #endif
4990
4991 void R_GLSL_Restart_f(void)
4992 {
4993         unsigned int i, limit;
4994         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4995                 Mem_Free(glslshaderstring);
4996         glslshaderstring = NULL;
4997         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4998                 Mem_Free(cgshaderstring);
4999         cgshaderstring = NULL;
5000         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
5001                 Mem_Free(hlslshaderstring);
5002         hlslshaderstring = NULL;
5003         switch(vid.renderpath)
5004         {
5005         case RENDERPATH_D3D9:
5006 #ifdef SUPPORTD3D
5007                 {
5008                         r_hlsl_permutation_t *p;
5009                         r_hlsl_permutation = NULL;
5010 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5011 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5012 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5013 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5014                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
5015                         for (i = 0;i < limit;i++)
5016                         {
5017                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
5018                                 {
5019                                         if (p->vertexshader)
5020                                                 IDirect3DVertexShader9_Release(p->vertexshader);
5021                                         if (p->pixelshader)
5022                                                 IDirect3DPixelShader9_Release(p->pixelshader);
5023                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
5024                                 }
5025                         }
5026                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
5027                 }
5028 #endif
5029                 break;
5030         case RENDERPATH_D3D10:
5031                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5032                 break;
5033         case RENDERPATH_D3D11:
5034                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5035                 break;
5036         case RENDERPATH_GL20:
5037                 {
5038                         r_glsl_permutation_t *p;
5039                         r_glsl_permutation = NULL;
5040                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
5041                         for (i = 0;i < limit;i++)
5042                         {
5043                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
5044                                 {
5045                                         GL_Backend_FreeProgram(p->program);
5046                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5047                                 }
5048                         }
5049                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5050                 }
5051                 break;
5052         case RENDERPATH_CGGL:
5053 #ifdef SUPPORTCG
5054                 {
5055                         r_cg_permutation_t *p;
5056                         r_cg_permutation = NULL;
5057                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5058                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5059                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5060                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5061                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5062                         for (i = 0;i < limit;i++)
5063                         {
5064                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5065                                 {
5066                                         if (p->vprogram)
5067                                                 cgDestroyProgram(p->vprogram);
5068                                         if (p->fprogram)
5069                                                 cgDestroyProgram(p->fprogram);
5070                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5071                                 }
5072                         }
5073                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5074                 }
5075 #endif
5076                 break;
5077         case RENDERPATH_GL13:
5078         case RENDERPATH_GL11:
5079                 break;
5080         }
5081 }
5082
5083 void R_GLSL_DumpShader_f(void)
5084 {
5085         int i;
5086         qfile_t *file;
5087
5088         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5089         if (file)
5090         {
5091                 FS_Print(file, "/* The engine may define the following macros:\n");
5092                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5093                 for (i = 0;i < SHADERMODE_COUNT;i++)
5094                         FS_Print(file, glslshadermodeinfo[i].pretext);
5095                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5096                         FS_Print(file, shaderpermutationinfo[i].pretext);
5097                 FS_Print(file, "*/\n");
5098                 FS_Print(file, builtinshaderstring);
5099                 FS_Close(file);
5100                 Con_Printf("glsl/default.glsl written\n");
5101         }
5102         else
5103                 Con_Printf("failed to write to glsl/default.glsl\n");
5104
5105 #ifdef SUPPORTCG
5106         file = FS_OpenRealFile("cg/default.cg", "w", false);
5107         if (file)
5108         {
5109                 FS_Print(file, "/* The engine may define the following macros:\n");
5110                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5111                 for (i = 0;i < SHADERMODE_COUNT;i++)
5112                         FS_Print(file, cgshadermodeinfo[i].pretext);
5113                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5114                         FS_Print(file, shaderpermutationinfo[i].pretext);
5115                 FS_Print(file, "*/\n");
5116                 FS_Print(file, builtincgshaderstring);
5117                 FS_Close(file);
5118                 Con_Printf("cg/default.cg written\n");
5119         }
5120         else
5121                 Con_Printf("failed to write to cg/default.cg\n");
5122 #endif
5123
5124 #ifdef SUPPORTD3D
5125         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5126         if (file)
5127         {
5128                 FS_Print(file, "/* The engine may define the following macros:\n");
5129                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5130                 for (i = 0;i < SHADERMODE_COUNT;i++)
5131                         FS_Print(file, hlslshadermodeinfo[i].pretext);
5132                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5133                         FS_Print(file, shaderpermutationinfo[i].pretext);
5134                 FS_Print(file, "*/\n");
5135                 FS_Print(file, builtincgshaderstring);
5136                 FS_Close(file);
5137                 Con_Printf("hlsl/default.hlsl written\n");
5138         }
5139         else
5140                 Con_Printf("failed to write to hlsl/default.hlsl\n");
5141 #endif
5142 }
5143
5144 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5145 {
5146         if (!second)
5147                 texturemode = GL_MODULATE;
5148         switch (vid.renderpath)
5149         {
5150         case RENDERPATH_D3D9:
5151 #ifdef SUPPORTD3D
5152                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5153                 R_Mesh_TexBind(GL20TU_FIRST , first );
5154                 R_Mesh_TexBind(GL20TU_SECOND, second);
5155 #endif
5156                 break;
5157         case RENDERPATH_D3D10:
5158                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5159                 break;
5160         case RENDERPATH_D3D11:
5161                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5162                 break;
5163         case RENDERPATH_GL20:
5164                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5165                 R_Mesh_TexBind(GL20TU_FIRST , first );
5166                 R_Mesh_TexBind(GL20TU_SECOND, second);
5167                 break;
5168         case RENDERPATH_CGGL:
5169 #ifdef SUPPORTCG
5170                 CHECKCGERROR
5171                 R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5172                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5173                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5174 #endif
5175                 break;
5176         case RENDERPATH_GL13:
5177                 R_Mesh_TexBind(0, first );
5178                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5179                 R_Mesh_TexBind(1, second);
5180                 if (second)
5181                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5182                 break;
5183         case RENDERPATH_GL11:
5184                 R_Mesh_TexBind(0, first );
5185                 break;
5186         }
5187 }
5188
5189 void R_SetupShader_DepthOrShadow(void)
5190 {
5191         switch (vid.renderpath)
5192         {
5193         case RENDERPATH_D3D9:
5194 #ifdef SUPPORTD3D
5195                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5196 #endif
5197                 break;
5198         case RENDERPATH_D3D10:
5199                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5200                 break;
5201         case RENDERPATH_D3D11:
5202                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5203                 break;
5204         case RENDERPATH_GL20:
5205                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5206                 break;
5207         case RENDERPATH_CGGL:
5208 #ifdef SUPPORTCG
5209                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5210 #endif
5211                 break;
5212         case RENDERPATH_GL13:
5213                 R_Mesh_TexBind(0, 0);
5214                 R_Mesh_TexBind(1, 0);
5215                 break;
5216         case RENDERPATH_GL11:
5217                 R_Mesh_TexBind(0, 0);
5218                 break;
5219         }
5220 }
5221
5222 void R_SetupShader_ShowDepth(void)
5223 {
5224         switch (vid.renderpath)
5225         {
5226         case RENDERPATH_D3D9:
5227 #ifdef SUPPORTHLSL
5228                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5229 #endif
5230                 break;
5231         case RENDERPATH_D3D10:
5232                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5233                 break;
5234         case RENDERPATH_D3D11:
5235                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5236                 break;
5237         case RENDERPATH_GL20:
5238                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5239                 break;
5240         case RENDERPATH_CGGL:
5241 #ifdef SUPPORTCG
5242                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5243 #endif
5244                 break;
5245         case RENDERPATH_GL13:
5246                 break;
5247         case RENDERPATH_GL11:
5248                 break;
5249         }
5250 }
5251
5252 extern qboolean r_shadow_usingdeferredprepass;
5253 extern cvar_t r_shadow_deferred_8bitrange;
5254 extern rtexture_t *r_shadow_attenuationgradienttexture;
5255 extern rtexture_t *r_shadow_attenuation2dtexture;
5256 extern rtexture_t *r_shadow_attenuation3dtexture;
5257 extern qboolean r_shadow_usingshadowmap2d;
5258 extern qboolean r_shadow_usingshadowmaportho;
5259 extern float r_shadow_shadowmap_texturescale[2];
5260 extern float r_shadow_shadowmap_parameters[4];
5261 extern qboolean r_shadow_shadowmapvsdct;
5262 extern qboolean r_shadow_shadowmapsampler;
5263 extern int r_shadow_shadowmappcf;
5264 extern rtexture_t *r_shadow_shadowmap2dtexture;
5265 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5266 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5267 extern matrix4x4_t r_shadow_shadowmapmatrix;
5268 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5269 extern int r_shadow_prepass_width;
5270 extern int r_shadow_prepass_height;
5271 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5272 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5273 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5274 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5275 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5276 extern cvar_t gl_mesh_separatearrays;
5277 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5278 {
5279         // a blendfunc allows colormod if:
5280         // a) it can never keep the destination pixel invariant, or
5281         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5282         // this is to prevent unintended side effects from colormod
5283
5284         // in formulas:
5285         // IF there is a (s, sa) for which for all (d, da),
5286         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5287         // THEN, for this (s, sa) and all (colormod, d, da):
5288         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5289         // OBVIOUSLY, this means that
5290         //   s*colormod * src(s*colormod, d, sa, da) = 0
5291         //   dst(s*colormod, d, sa, da)              = 1
5292
5293         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5294
5295         // main condition to leave dst color invariant:
5296         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5297         //   src == GL_ZERO:
5298         //     s * 0 + d * dst(s, d, sa, da) == d
5299         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5300         //       => colormod is a problem for GL_SRC_COLOR only
5301         //   src == GL_ONE:
5302         //     s + d * dst(s, d, sa, da) == d
5303         //       => s == 0
5304         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5305         //       => colormod is never problematic for these
5306         //   src == GL_SRC_COLOR:
5307         //     s*s + d * dst(s, d, sa, da) == d
5308         //       => s == 0
5309         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5310         //       => colormod is never problematic for these
5311         //   src == GL_ONE_MINUS_SRC_COLOR:
5312         //     s*(1-s) + d * dst(s, d, sa, da) == d
5313         //       => s == 0 or s == 1
5314         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5315         //       => colormod is a problem for GL_SRC_COLOR only
5316         //   src == GL_DST_COLOR
5317         //     s*d + d * dst(s, d, sa, da) == d
5318         //       => s == 1
5319         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5320         //       => colormod is always a problem
5321         //     or
5322         //       => s == 0
5323         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5324         //       => colormod is never problematic for these
5325         //       => BUT, we do not know s! We must assume it is problematic
5326         //       then... except in GL_ONE case, where we know all invariant
5327         //       cases are fine
5328         //   src == GL_ONE_MINUS_DST_COLOR
5329         //     s*(1-d) + d * dst(s, d, sa, da) == d
5330         //       => s == 0 (1-d is impossible to handle for our desired result)
5331         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5332         //       => colormod is never problematic for these
5333         //   src == GL_SRC_ALPHA
5334         //     s*sa + d * dst(s, d, sa, da) == d
5335         //       => s == 0, or sa == 0
5336         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5337         //       => colormod breaks in the case GL_SRC_COLOR only
5338         //   src == GL_ONE_MINUS_SRC_ALPHA
5339         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5340         //       => s == 0, or sa == 1
5341         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5342         //       => colormod breaks in the case GL_SRC_COLOR only
5343         //   src == GL_DST_ALPHA
5344         //     s*da + d * dst(s, d, sa, da) == d
5345         //       => s == 0
5346         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5347         //       => colormod is never problematic for these
5348
5349         switch(src)
5350         {
5351                 case GL_ZERO:
5352                 case GL_ONE_MINUS_SRC_COLOR:
5353                 case GL_SRC_ALPHA:
5354                 case GL_ONE_MINUS_SRC_ALPHA:
5355                         if(dst == GL_SRC_COLOR)
5356                                 return false;
5357                         return true;
5358                 case GL_ONE:
5359                 case GL_SRC_COLOR:
5360                 case GL_ONE_MINUS_DST_COLOR:
5361                 case GL_DST_ALPHA:
5362                 case GL_ONE_MINUS_DST_ALPHA:
5363                         return true;
5364                 case GL_DST_COLOR:
5365                         if(dst == GL_ONE)
5366                                 return true;
5367                         return false;
5368                 default:
5369                         return false;
5370         }
5371 }
5372 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)
5373 {
5374         // select a permutation of the lighting shader appropriate to this
5375         // combination of texture, entity, light source, and fogging, only use the
5376         // minimum features necessary to avoid wasting rendering time in the
5377         // fragment shader on features that are not being used
5378         unsigned int permutation = 0;
5379         unsigned int mode = 0;
5380         qboolean allow_colormod;
5381         static float dummy_colormod[3] = {1, 1, 1};
5382         float *colormod = rsurface.colormod;
5383         float m16f[16];
5384         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5385         if (rsurfacepass == RSURFPASS_BACKGROUND)
5386         {
5387                 // distorted background
5388                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5389                 {
5390                         mode = SHADERMODE_WATER;
5391                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
5392                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
5393                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5394                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5395                 }
5396                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5397                 {
5398                         mode = SHADERMODE_REFRACTION;
5399                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5400                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5401                 }
5402                 else
5403                 {
5404                         mode = SHADERMODE_GENERIC;
5405                         permutation |= SHADERPERMUTATION_DIFFUSE;
5406                         GL_BlendFunc(GL_ONE, GL_ZERO);
5407                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5408                 }
5409                 GL_AlphaTest(false);
5410         }
5411         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5412         {
5413                 if (r_glsl_offsetmapping.integer)
5414                 {
5415                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5416                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5417                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5418                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5419                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5420                         {
5421                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5422                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5423                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5424                         }
5425                 }
5426                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5427                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5428                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5429                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5430                 // normalmap (deferred prepass), may use alpha test on diffuse
5431                 mode = SHADERMODE_DEFERREDGEOMETRY;
5432                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5433                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5434                 GL_AlphaTest(false);
5435                 GL_BlendFunc(GL_ONE, GL_ZERO);
5436                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5437         }
5438         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5439         {
5440                 if (r_glsl_offsetmapping.integer)
5441                 {
5442                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5443                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5444                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5445                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5446                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5447                         {
5448                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5449                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5450                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5451                         }
5452                 }
5453                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5454                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5455                 // light source
5456                 mode = SHADERMODE_LIGHTSOURCE;
5457                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5458                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5459                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5460                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5461                 if (diffusescale > 0)
5462                         permutation |= SHADERPERMUTATION_DIFFUSE;
5463                 if (specularscale > 0)
5464                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5465                 if (r_refdef.fogenabled)
5466                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5467                 if (rsurface.texture->colormapping)
5468                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5469                 if (r_shadow_usingshadowmap2d)
5470                 {
5471                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5472                         if(r_shadow_shadowmapvsdct)
5473                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5474
5475                         if (r_shadow_shadowmapsampler)
5476                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5477                         if (r_shadow_shadowmappcf > 1)
5478                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5479                         else if (r_shadow_shadowmappcf)
5480                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5481                 }
5482                 if (rsurface.texture->reflectmasktexture)
5483                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5484                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5485                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5486                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5487         }
5488         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5489         {
5490                 if (r_glsl_offsetmapping.integer)
5491                 {
5492                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5493                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5494                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5495                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5496                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5497                         {
5498                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5499                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5500                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5501                         }
5502                 }
5503                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5504                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5505                 // unshaded geometry (fullbright or ambient model lighting)
5506                 mode = SHADERMODE_FLATCOLOR;
5507                 ambientscale = diffusescale = specularscale = 0;
5508                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5509                         permutation |= SHADERPERMUTATION_GLOW;
5510                 if (r_refdef.fogenabled)
5511                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5512                 if (rsurface.texture->colormapping)
5513                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5514                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5515                 {
5516                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5517                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5518
5519                         if (r_shadow_shadowmapsampler)
5520                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5521                         if (r_shadow_shadowmappcf > 1)
5522                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5523                         else if (r_shadow_shadowmappcf)
5524                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5525                 }
5526                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5527                         permutation |= SHADERPERMUTATION_REFLECTION;
5528                 if (rsurface.texture->reflectmasktexture)
5529                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5530                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5531                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5532                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5533         }
5534         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5535         {
5536                 if (r_glsl_offsetmapping.integer)
5537                 {
5538                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5539                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5540                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5541                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5542                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5543                         {
5544                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5545                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5546                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5547                         }
5548                 }
5549                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5550                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5551                 // directional model lighting
5552                 mode = SHADERMODE_LIGHTDIRECTION;
5553                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5554                         permutation |= SHADERPERMUTATION_GLOW;
5555                 permutation |= SHADERPERMUTATION_DIFFUSE;
5556                 if (specularscale > 0)
5557                         permutation |= SHADERPERMUTATION_SPECULAR;
5558                 if (r_refdef.fogenabled)
5559                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5560                 if (rsurface.texture->colormapping)
5561                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5562                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5563                 {
5564                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5565                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5566
5567                         if (r_shadow_shadowmapsampler)
5568                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5569                         if (r_shadow_shadowmappcf > 1)
5570                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5571                         else if (r_shadow_shadowmappcf)
5572                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5573                 }
5574                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5575                         permutation |= SHADERPERMUTATION_REFLECTION;
5576                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5577                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5578                 if (rsurface.texture->reflectmasktexture)
5579                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5580                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5581                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5582                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5583         }
5584         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5585         {
5586                 if (r_glsl_offsetmapping.integer)
5587                 {
5588                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5589                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5590                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5591                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5592                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5593                         {
5594                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5595                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5596                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5597                         }
5598                 }
5599                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5600                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5601                 // ambient model lighting
5602                 mode = SHADERMODE_LIGHTDIRECTION;
5603                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5604                         permutation |= SHADERPERMUTATION_GLOW;
5605                 if (r_refdef.fogenabled)
5606                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5607                 if (rsurface.texture->colormapping)
5608                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5609                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5610                 {
5611                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5612                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5613
5614                         if (r_shadow_shadowmapsampler)
5615                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5616                         if (r_shadow_shadowmappcf > 1)
5617                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5618                         else if (r_shadow_shadowmappcf)
5619                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5620                 }
5621                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5622                         permutation |= SHADERPERMUTATION_REFLECTION;
5623                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5624                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5625                 if (rsurface.texture->reflectmasktexture)
5626                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5627                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5628                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5629                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5630         }
5631         else
5632         {
5633                 if (r_glsl_offsetmapping.integer)
5634                 {
5635                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5636                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5637                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5638                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5639                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5640                         {
5641                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5642                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5643                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5644                         }
5645                 }
5646                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5647                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5648                 // lightmapped wall
5649                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5650                         permutation |= SHADERPERMUTATION_GLOW;
5651                 if (r_refdef.fogenabled)
5652                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5653                 if (rsurface.texture->colormapping)
5654                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5655                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5656                 {
5657                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5658                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5659
5660                         if (r_shadow_shadowmapsampler)
5661                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5662                         if (r_shadow_shadowmappcf > 1)
5663                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5664                         else if (r_shadow_shadowmappcf)
5665                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5666                 }
5667                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5668                         permutation |= SHADERPERMUTATION_REFLECTION;
5669                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5670                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5671                 if (rsurface.texture->reflectmasktexture)
5672                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5673                 if (FAKELIGHT_ENABLED)
5674                 {
5675                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5676                         mode = SHADERMODE_FAKELIGHT;
5677                         permutation |= SHADERPERMUTATION_DIFFUSE;
5678                         if (specularscale > 0)
5679                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5680                 }
5681                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5682                 {
5683                         // deluxemapping (light direction texture)
5684                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5685                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5686                         else
5687                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5688                         permutation |= SHADERPERMUTATION_DIFFUSE;
5689                         if (specularscale > 0)
5690                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5691                 }
5692                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5693                 {
5694                         // fake deluxemapping (uniform light direction in tangentspace)
5695                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5696                         permutation |= SHADERPERMUTATION_DIFFUSE;
5697                         if (specularscale > 0)
5698                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5699                 }
5700                 else if (rsurface.uselightmaptexture)
5701                 {
5702                         // ordinary lightmapping (q1bsp, q3bsp)
5703                         mode = SHADERMODE_LIGHTMAP;
5704                 }
5705                 else
5706                 {
5707                         // ordinary vertex coloring (q3bsp)
5708                         mode = SHADERMODE_VERTEXCOLOR;
5709                 }
5710                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5711                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5712                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5713         }
5714         if(!allow_colormod)
5715                 colormod = dummy_colormod;
5716         switch(vid.renderpath)
5717         {
5718         case RENDERPATH_D3D9:
5719 #ifdef SUPPORTD3D
5720                 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);
5721                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5722                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5723                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5724                 if (mode == SHADERMODE_LIGHTSOURCE)
5725                 {
5726                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5727                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5728                 }
5729                 else
5730                 {
5731                         if (mode == SHADERMODE_LIGHTDIRECTION)                                   
5732                         {
5733                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5734                         }
5735                 }
5736                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5737                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5738                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5739                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5740                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5741
5742                 if (mode == SHADERMODE_LIGHTSOURCE)
5743                 {
5744                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5745                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5746                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5747                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5748                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5749
5750                         // additive passes are only darkened by fog, not tinted
5751                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5752                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5753                 }
5754                 else
5755                 {
5756                         if (mode == SHADERMODE_FLATCOLOR)
5757                         {
5758                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5759                         }
5760                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5761                         {
5762                                 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]);
5763                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5764                                 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);
5765                                 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);
5766                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5767                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5768                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5769                         }
5770                         else
5771                         {
5772                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5773                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5774                                 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);
5775                                 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);
5776                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5777                         }
5778                         // additive passes are only darkened by fog, not tinted
5779                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5780                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5781                         else
5782                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5783                         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);
5784                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5785                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5786                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5787                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5788                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5789                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5790                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5791                         if (mode == SHADERMODE_WATER)
5792                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5793                 }
5794                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5795                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5796                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5797                 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));
5798                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5799                 if (rsurface.texture->pantstexture)
5800                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5801                 else
5802                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5803                 if (rsurface.texture->shirttexture)
5804                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5805                 else
5806                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5807                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5808                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5809                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5810                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5811                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5812                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5813                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5814
5815                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5816                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5817                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5818                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5819                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5820                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5821                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5822                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5823                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5824                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5825                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5826                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5827                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5828                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5829                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5830                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5831                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5832                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5833                 {
5834                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5835                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5836                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5837                 }
5838                 else
5839                 {
5840                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5841                 }
5842 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5843 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5844                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5845                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5846                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5847                 {
5848                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5849                         if (rsurface.rtlight)
5850                         {
5851                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5852                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5853                         }
5854                 }
5855 #endif
5856                 break;
5857         case RENDERPATH_D3D10:
5858                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5859                 break;
5860         case RENDERPATH_D3D11:
5861                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5862                 break;
5863         case RENDERPATH_GL20:
5864                 if (gl_mesh_separatearrays.integer)
5865                 {
5866                         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);
5867                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5868                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5869                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5870                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5871                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5872                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5873                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5874                 }
5875                 else
5876                 {
5877                         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);
5878                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5879                 }
5880                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5881                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5882                 if (mode == SHADERMODE_LIGHTSOURCE)
5883                 {
5884                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5885                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5886                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5887                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5888                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5889                         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);
5890         
5891                         // additive passes are only darkened by fog, not tinted
5892                         if (r_glsl_permutation->loc_FogColor >= 0)
5893                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5894                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5895                 }
5896                 else
5897                 {
5898                         if (mode == SHADERMODE_FLATCOLOR)
5899                         {
5900                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5901                         }
5902                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5903                         {
5904                                 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 * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
5905                                 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]);
5906                                 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);
5907                                 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);
5908                                 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);
5909                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
5910                                 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]);
5911                         }
5912                         else
5913                         {
5914                                 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]);
5915                                 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]);
5916                                 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);
5917                                 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);
5918                                 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);
5919                         }
5920                         // additive passes are only darkened by fog, not tinted
5921                         if (r_glsl_permutation->loc_FogColor >= 0)
5922                         {
5923                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5924                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5925                                 else
5926                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5927                         }
5928                         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);
5929                         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]);
5930                         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]);
5931                         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]);
5932                         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]);
5933                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5934                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5935                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5936                         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]);
5937                 }
5938                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5939                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5940                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5941                 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]);
5942                 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]);
5943
5944                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5945                 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));
5946                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5947                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5948                 {
5949                         if (rsurface.texture->pantstexture)
5950                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5951                         else
5952                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5953                 }
5954                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5955                 {
5956                         if (rsurface.texture->shirttexture)
5957                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5958                         else
5959                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5960                 }
5961                 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]);
5962                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5963                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5964                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5965                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5966                 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]);
5967                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5968
5969         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5970         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5971         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5972                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5973                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5974                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5975                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5976                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5977                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5978                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5979                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5980                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5981                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5982                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5983                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5984                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5985                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5986                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5987                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5988                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5989                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5990                 {
5991                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5992                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5993                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5994                 }
5995                 else
5996                 {
5997                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5998                 }
5999 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
6000 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
6001                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
6002                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
6003                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6004                 {
6005                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
6006                         if (rsurface.rtlight)
6007                         {
6008                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
6009                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
6010                         }
6011                 }
6012                 CHECKGLERROR
6013                 break;
6014         case RENDERPATH_CGGL:
6015 #ifdef SUPPORTCG
6016                 if (gl_mesh_separatearrays.integer)
6017                 {
6018                         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);
6019                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
6020                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
6021                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
6022                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
6023                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6024                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6025                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6026                 }
6027                 else
6028                 {
6029                         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);
6030                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6031                 }
6032                 R_SetupShader_SetPermutationCG(mode, permutation);
6033                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6034                 if (mode == SHADERMODE_LIGHTSOURCE)
6035                 {
6036                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6037                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6038                 }
6039                 else
6040                 {
6041                         if (mode == SHADERMODE_LIGHTDIRECTION)
6042                         {
6043                                 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
6044                         }
6045                 }
6046                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6047                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6048                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6049                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6050                 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
6051                 CHECKGLERROR
6052
6053                 if (mode == SHADERMODE_LIGHTSOURCE)
6054                 {
6055                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6056                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6057                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6058                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6059                         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
6060
6061                         // additive passes are only darkened by fog, not tinted
6062                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6063                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6064                 }
6065                 else
6066                 {
6067                         if (mode == SHADERMODE_FLATCOLOR)
6068                         {
6069                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6070                         }
6071                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6072                         {
6073                                 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
6074                                 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
6075                                 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
6076                                 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
6077                                 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
6078                                 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
6079                                 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
6080                         }
6081                         else
6082                         {
6083                                 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
6084                                 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
6085                                 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
6086                                 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
6087                                 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
6088                         }
6089                         // additive passes are only darkened by fog, not tinted
6090                         if (r_cg_permutation->fp_FogColor)
6091                         {
6092                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6093                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6094                                 else
6095                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6096                                 CHECKCGERROR
6097                         }
6098                         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
6099                         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
6100                         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
6101                         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
6102                         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
6103                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6104                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6105                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6106                         if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6107                 }
6108                 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
6109                 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
6110                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6111                 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
6112                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6113                 if (r_cg_permutation->fp_Color_Pants)
6114                 {
6115                         if (rsurface.texture->pantstexture)
6116                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6117                         else
6118                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6119                         CHECKCGERROR
6120                 }
6121                 if (r_cg_permutation->fp_Color_Shirt)
6122                 {
6123                         if (rsurface.texture->shirttexture)
6124                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6125                         else
6126                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6127                         CHECKCGERROR
6128                 }
6129                 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
6130                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6131                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6132                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6133                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6134                 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
6135                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6136
6137         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
6138         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
6139         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
6140                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
6141                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
6142                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
6143                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
6144                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
6145                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
6146                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
6147                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
6148                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
6149                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
6150                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
6151                 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
6152                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
6153                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
6154                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6155                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6156                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6157                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6158                 {
6159                         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
6160                         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
6161                         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
6162                 }
6163                 else
6164                 {
6165                         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
6166                 }
6167                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6168                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6169                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
6170                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
6171                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6172                 {
6173                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6174                         if (rsurface.rtlight)
6175                         {
6176                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6177                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6178                         }
6179                 }
6180
6181                 CHECKGLERROR
6182 #endif
6183                 break;
6184         case RENDERPATH_GL13:
6185         case RENDERPATH_GL11:
6186                 break;
6187         }
6188 }
6189
6190 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6191 {
6192         // select a permutation of the lighting shader appropriate to this
6193         // combination of texture, entity, light source, and fogging, only use the
6194         // minimum features necessary to avoid wasting rendering time in the
6195         // fragment shader on features that are not being used
6196         unsigned int permutation = 0;
6197         unsigned int mode = 0;
6198         const float *lightcolorbase = rtlight->currentcolor;
6199         float ambientscale = rtlight->ambientscale;
6200         float diffusescale = rtlight->diffusescale;
6201         float specularscale = rtlight->specularscale;
6202         // this is the location of the light in view space
6203         vec3_t viewlightorigin;
6204         // this transforms from view space (camera) to light space (cubemap)
6205         matrix4x4_t viewtolight;
6206         matrix4x4_t lighttoview;
6207         float viewtolight16f[16];
6208         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6209         // light source
6210         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6211         if (rtlight->currentcubemap != r_texture_whitecube)
6212                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6213         if (diffusescale > 0)
6214                 permutation |= SHADERPERMUTATION_DIFFUSE;
6215         if (specularscale > 0)
6216                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6217         if (r_shadow_usingshadowmap2d)
6218         {
6219                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6220                 if (r_shadow_shadowmapvsdct)
6221                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6222
6223                 if (r_shadow_shadowmapsampler)
6224                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6225                 if (r_shadow_shadowmappcf > 1)
6226                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6227                 else if (r_shadow_shadowmappcf)
6228                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6229         }
6230         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6231         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6232         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6233         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6234         switch(vid.renderpath)
6235         {
6236         case RENDERPATH_D3D9:
6237 #ifdef SUPPORTD3D
6238                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6239                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6240                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6241                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6242                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6243                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6244                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6245                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6246                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6247                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6248                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6249
6250                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6251                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
6252                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6253                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6254                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
6255                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6256 #endif
6257                 break;
6258         case RENDERPATH_D3D10:
6259                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6260                 break;
6261         case RENDERPATH_D3D11:
6262                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6263                 break;
6264         case RENDERPATH_GL20:
6265                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6266                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6267                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6268                 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);
6269                 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);
6270                 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);
6271                 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]);
6272                 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]);
6273                 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) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6274                 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]);
6275                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6276
6277                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6278                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6279                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6280                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6281                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6282                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6283                 break;
6284         case RENDERPATH_CGGL:
6285 #ifdef SUPPORTCG
6286                 R_SetupShader_SetPermutationCG(mode, permutation);
6287                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6288                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6289                 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
6290                 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
6291                 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
6292                 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
6293                 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
6294                 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) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6295                 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
6296                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6297
6298                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6299                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6300                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6301                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6302                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6303                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6304 #endif
6305                 break;
6306         case RENDERPATH_GL13:
6307         case RENDERPATH_GL11:
6308                 break;
6309         }
6310 }
6311
6312 #define SKINFRAME_HASH 1024
6313
6314 typedef struct
6315 {
6316         int loadsequence; // incremented each level change
6317         memexpandablearray_t array;
6318         skinframe_t *hash[SKINFRAME_HASH];
6319 }
6320 r_skinframe_t;
6321 r_skinframe_t r_skinframe;
6322
6323 void R_SkinFrame_PrepareForPurge(void)
6324 {
6325         r_skinframe.loadsequence++;
6326         // wrap it without hitting zero
6327         if (r_skinframe.loadsequence >= 200)
6328                 r_skinframe.loadsequence = 1;
6329 }
6330
6331 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6332 {
6333         if (!skinframe)
6334                 return;
6335         // mark the skinframe as used for the purging code
6336         skinframe->loadsequence = r_skinframe.loadsequence;
6337 }
6338
6339 void R_SkinFrame_Purge(void)
6340 {
6341         int i;
6342         skinframe_t *s;
6343         for (i = 0;i < SKINFRAME_HASH;i++)
6344         {
6345                 for (s = r_skinframe.hash[i];s;s = s->next)
6346                 {
6347                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6348                         {
6349                                 if (s->merged == s->base)
6350                                         s->merged = NULL;
6351                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6352                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6353                                 R_PurgeTexture(s->merged);s->merged = NULL;
6354                                 R_PurgeTexture(s->base  );s->base   = NULL;
6355                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6356                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6357                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6358                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6359                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6360                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6361                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6362                                 s->loadsequence = 0;
6363                         }
6364                 }
6365         }
6366 }
6367
6368 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6369         skinframe_t *item;
6370         char basename[MAX_QPATH];
6371
6372         Image_StripImageExtension(name, basename, sizeof(basename));
6373
6374         if( last == NULL ) {
6375                 int hashindex;
6376                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6377                 item = r_skinframe.hash[hashindex];
6378         } else {
6379                 item = last->next;
6380         }
6381
6382         // linearly search through the hash bucket
6383         for( ; item ; item = item->next ) {
6384                 if( !strcmp( item->basename, basename ) ) {
6385                         return item;
6386                 }
6387         }
6388         return NULL;
6389 }
6390
6391 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6392 {
6393         skinframe_t *item;
6394         int hashindex;
6395         char basename[MAX_QPATH];
6396
6397         Image_StripImageExtension(name, basename, sizeof(basename));
6398
6399         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6400         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6401                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6402                         break;
6403
6404         if (!item) {
6405                 rtexture_t *dyntexture;
6406                 // check whether its a dynamic texture
6407                 dyntexture = CL_GetDynTexture( basename );
6408                 if (!add && !dyntexture)
6409                         return NULL;
6410                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6411                 memset(item, 0, sizeof(*item));
6412                 strlcpy(item->basename, basename, sizeof(item->basename));
6413                 item->base = dyntexture; // either NULL or dyntexture handle
6414                 item->textureflags = textureflags;
6415                 item->comparewidth = comparewidth;
6416                 item->compareheight = compareheight;
6417                 item->comparecrc = comparecrc;
6418                 item->next = r_skinframe.hash[hashindex];
6419                 r_skinframe.hash[hashindex] = item;
6420         }
6421         else if( item->base == NULL )
6422         {
6423                 rtexture_t *dyntexture;
6424                 // check whether its a dynamic texture
6425                 // 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]
6426                 dyntexture = CL_GetDynTexture( basename );
6427                 item->base = dyntexture; // either NULL or dyntexture handle
6428         }
6429
6430         R_SkinFrame_MarkUsed(item);
6431         return item;
6432 }
6433
6434 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6435         { \
6436                 unsigned long long avgcolor[5], wsum; \
6437                 int pix, comp, w; \
6438                 avgcolor[0] = 0; \
6439                 avgcolor[1] = 0; \
6440                 avgcolor[2] = 0; \
6441                 avgcolor[3] = 0; \
6442                 avgcolor[4] = 0; \
6443                 wsum = 0; \
6444                 for(pix = 0; pix < cnt; ++pix) \
6445                 { \
6446                         w = 0; \
6447                         for(comp = 0; comp < 3; ++comp) \
6448                                 w += getpixel; \
6449                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6450                         { \
6451                                 ++wsum; \
6452                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6453                                 w = getpixel; \
6454                                 for(comp = 0; comp < 3; ++comp) \
6455                                         avgcolor[comp] += getpixel * w; \
6456                                 avgcolor[3] += w; \
6457                         } \
6458                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6459                         avgcolor[4] += getpixel; \
6460                 } \
6461                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6462                         avgcolor[3] = 1; \
6463                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6464                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6465                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6466                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6467         }
6468
6469 extern cvar_t gl_picmip;
6470 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6471 {
6472         int j;
6473         unsigned char *pixels;
6474         unsigned char *bumppixels;
6475         unsigned char *basepixels = NULL;
6476         int basepixels_width = 0;
6477         int basepixels_height = 0;
6478         skinframe_t *skinframe;
6479         rtexture_t *ddsbase = NULL;
6480         qboolean ddshasalpha = false;
6481         float ddsavgcolor[4];
6482         char basename[MAX_QPATH];
6483         int miplevel = R_PicmipForFlags(textureflags);
6484         int savemiplevel = miplevel;
6485         int mymiplevel;
6486
6487         if (cls.state == ca_dedicated)
6488                 return NULL;
6489
6490         // return an existing skinframe if already loaded
6491         // if loading of the first image fails, don't make a new skinframe as it
6492         // would cause all future lookups of this to be missing
6493         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6494         if (skinframe && skinframe->base)
6495                 return skinframe;
6496
6497         Image_StripImageExtension(name, basename, sizeof(basename));
6498
6499         // check for DDS texture file first
6500         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6501         {
6502                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6503                 if (basepixels == NULL)
6504                         return NULL;
6505         }
6506
6507         // FIXME handle miplevel
6508
6509         if (developer_loading.integer)
6510                 Con_Printf("loading skin \"%s\"\n", name);
6511
6512         // we've got some pixels to store, so really allocate this new texture now
6513         if (!skinframe)
6514                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6515         skinframe->stain = NULL;
6516         skinframe->merged = NULL;
6517         skinframe->base = NULL;
6518         skinframe->pants = NULL;
6519         skinframe->shirt = NULL;
6520         skinframe->nmap = NULL;
6521         skinframe->gloss = NULL;
6522         skinframe->glow = NULL;
6523         skinframe->fog = NULL;
6524         skinframe->reflect = NULL;
6525         skinframe->hasalpha = false;
6526
6527         if (ddsbase)
6528         {
6529                 skinframe->base = ddsbase;
6530                 skinframe->hasalpha = ddshasalpha;
6531                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6532                 if (r_loadfog && skinframe->hasalpha)
6533                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6534                 //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]);
6535         }
6536         else
6537         {
6538                 basepixels_width = image_width;
6539                 basepixels_height = image_height;
6540                 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);
6541                 if (textureflags & TEXF_ALPHA)
6542                 {
6543                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6544                         {
6545                                 if (basepixels[j] < 255)
6546                                 {
6547                                         skinframe->hasalpha = true;
6548                                         break;
6549                                 }
6550                         }
6551                         if (r_loadfog && skinframe->hasalpha)
6552                         {
6553                                 // has transparent pixels
6554                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6555                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6556                                 {
6557                                         pixels[j+0] = 255;
6558                                         pixels[j+1] = 255;
6559                                         pixels[j+2] = 255;
6560                                         pixels[j+3] = basepixels[j+3];
6561                                 }
6562                                 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);
6563                                 Mem_Free(pixels);
6564                         }
6565                 }
6566                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6567                 //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]);
6568                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6569                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6570                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6571                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6572         }
6573
6574         if (r_loaddds)
6575         {
6576                 mymiplevel = savemiplevel;
6577                 if (r_loadnormalmap)
6578                         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);
6579                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6580                 if (r_loadgloss)
6581                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6582                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6583                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6584                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6585         }
6586
6587         // _norm is the name used by tenebrae and has been adopted as standard
6588         if (r_loadnormalmap && skinframe->nmap == NULL)
6589         {
6590                 mymiplevel = savemiplevel;
6591                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6592                 {
6593                         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);
6594                         Mem_Free(pixels);
6595                         pixels = NULL;
6596                 }
6597                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6598                 {
6599                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6600                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6601                         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);
6602                         Mem_Free(pixels);
6603                         Mem_Free(bumppixels);
6604                 }
6605                 else if (r_shadow_bumpscale_basetexture.value > 0)
6606                 {
6607                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6608                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6609                         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);
6610                         Mem_Free(pixels);
6611                 }
6612                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6613                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6614         }
6615
6616         // _luma is supported only for tenebrae compatibility
6617         // _glow is the preferred name
6618         mymiplevel = savemiplevel;
6619         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))))
6620         {
6621                 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);
6622                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6623                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6624                 Mem_Free(pixels);pixels = NULL;
6625         }
6626
6627         mymiplevel = savemiplevel;
6628         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6629         {
6630                 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);
6631                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6632                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6633                 Mem_Free(pixels);
6634                 pixels = NULL;
6635         }
6636
6637         mymiplevel = savemiplevel;
6638         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6639         {
6640                 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);
6641                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6642                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6643                 Mem_Free(pixels);
6644                 pixels = NULL;
6645         }
6646
6647         mymiplevel = savemiplevel;
6648         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6649         {
6650                 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);
6651                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6652                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6653                 Mem_Free(pixels);
6654                 pixels = NULL;
6655         }
6656
6657         mymiplevel = savemiplevel;
6658         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6659         {
6660                 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);
6661                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6662                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6663                 Mem_Free(pixels);
6664                 pixels = NULL;
6665         }
6666
6667         if (basepixels)
6668                 Mem_Free(basepixels);
6669
6670         return skinframe;
6671 }
6672
6673 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6674 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6675 {
6676         int i;
6677         unsigned char *temp1, *temp2;
6678         skinframe_t *skinframe;
6679
6680         if (cls.state == ca_dedicated)
6681                 return NULL;
6682
6683         // if already loaded just return it, otherwise make a new skinframe
6684         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6685         if (skinframe && skinframe->base)
6686                 return skinframe;
6687
6688         skinframe->stain = NULL;
6689         skinframe->merged = NULL;
6690         skinframe->base = NULL;
6691         skinframe->pants = NULL;
6692         skinframe->shirt = NULL;
6693         skinframe->nmap = NULL;
6694         skinframe->gloss = NULL;
6695         skinframe->glow = NULL;
6696         skinframe->fog = NULL;
6697         skinframe->reflect = NULL;
6698         skinframe->hasalpha = false;
6699
6700         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6701         if (!skindata)
6702                 return NULL;
6703
6704         if (developer_loading.integer)
6705                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6706
6707         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6708         {
6709                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6710                 temp2 = temp1 + width * height * 4;
6711                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6712                 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);
6713                 Mem_Free(temp1);
6714         }
6715         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6716         if (textureflags & TEXF_ALPHA)
6717         {
6718                 for (i = 3;i < width * height * 4;i += 4)
6719                 {
6720                         if (skindata[i] < 255)
6721                         {
6722                                 skinframe->hasalpha = true;
6723                                 break;
6724                         }
6725                 }
6726                 if (r_loadfog && skinframe->hasalpha)
6727                 {
6728                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6729                         memcpy(fogpixels, skindata, width * height * 4);
6730                         for (i = 0;i < width * height * 4;i += 4)
6731                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6732                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6733                         Mem_Free(fogpixels);
6734                 }
6735         }
6736
6737         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6738         //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]);
6739
6740         return skinframe;
6741 }
6742
6743 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6744 {
6745         int i;
6746         int featuresmask;
6747         skinframe_t *skinframe;
6748
6749         if (cls.state == ca_dedicated)
6750                 return NULL;
6751
6752         // if already loaded just return it, otherwise make a new skinframe
6753         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6754         if (skinframe && skinframe->base)
6755                 return skinframe;
6756
6757         skinframe->stain = NULL;
6758         skinframe->merged = NULL;
6759         skinframe->base = NULL;
6760         skinframe->pants = NULL;
6761         skinframe->shirt = NULL;
6762         skinframe->nmap = NULL;
6763         skinframe->gloss = NULL;
6764         skinframe->glow = NULL;
6765         skinframe->fog = NULL;
6766         skinframe->reflect = NULL;
6767         skinframe->hasalpha = false;
6768
6769         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6770         if (!skindata)
6771                 return NULL;
6772
6773         if (developer_loading.integer)
6774                 Con_Printf("loading quake skin \"%s\"\n", name);
6775
6776         // 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)
6777         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6778         memcpy(skinframe->qpixels, skindata, width*height);
6779         skinframe->qwidth = width;
6780         skinframe->qheight = height;
6781
6782         featuresmask = 0;
6783         for (i = 0;i < width * height;i++)
6784                 featuresmask |= palette_featureflags[skindata[i]];
6785
6786         skinframe->hasalpha = false;
6787         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6788         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6789         skinframe->qgeneratemerged = true;
6790         skinframe->qgeneratebase = skinframe->qhascolormapping;
6791         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6792
6793         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6794         //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]);
6795
6796         return skinframe;
6797 }
6798
6799 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6800 {
6801         int width;
6802         int height;
6803         unsigned char *skindata;
6804
6805         if (!skinframe->qpixels)
6806                 return;
6807
6808         if (!skinframe->qhascolormapping)
6809                 colormapped = false;
6810
6811         if (colormapped)
6812         {
6813                 if (!skinframe->qgeneratebase)
6814                         return;
6815         }
6816         else
6817         {
6818                 if (!skinframe->qgeneratemerged)
6819                         return;
6820         }
6821
6822         width = skinframe->qwidth;
6823         height = skinframe->qheight;
6824         skindata = skinframe->qpixels;
6825
6826         if (skinframe->qgeneratenmap)
6827         {
6828                 unsigned char *temp1, *temp2;
6829                 skinframe->qgeneratenmap = false;
6830                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6831                 temp2 = temp1 + width * height * 4;
6832                 // use either a custom palette or the quake palette
6833                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6834                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6835                 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);
6836                 Mem_Free(temp1);
6837         }
6838
6839         if (skinframe->qgenerateglow)
6840         {
6841                 skinframe->qgenerateglow = false;
6842                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6843         }
6844
6845         if (colormapped)
6846         {
6847                 skinframe->qgeneratebase = false;
6848                 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);
6849                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6850                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6851         }
6852         else
6853         {
6854                 skinframe->qgeneratemerged = false;
6855                 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);
6856         }
6857
6858         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6859         {
6860                 Mem_Free(skinframe->qpixels);
6861                 skinframe->qpixels = NULL;
6862         }
6863 }
6864
6865 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)
6866 {
6867         int i;
6868         skinframe_t *skinframe;
6869
6870         if (cls.state == ca_dedicated)
6871                 return NULL;
6872
6873         // if already loaded just return it, otherwise make a new skinframe
6874         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6875         if (skinframe && skinframe->base)
6876                 return skinframe;
6877
6878         skinframe->stain = NULL;
6879         skinframe->merged = NULL;
6880         skinframe->base = NULL;
6881         skinframe->pants = NULL;
6882         skinframe->shirt = NULL;
6883         skinframe->nmap = NULL;
6884         skinframe->gloss = NULL;
6885         skinframe->glow = NULL;
6886         skinframe->fog = NULL;
6887         skinframe->reflect = NULL;
6888         skinframe->hasalpha = false;
6889
6890         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6891         if (!skindata)
6892                 return NULL;
6893
6894         if (developer_loading.integer)
6895                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6896
6897         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6898         if (textureflags & TEXF_ALPHA)
6899         {
6900                 for (i = 0;i < width * height;i++)
6901                 {
6902                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6903                         {
6904                                 skinframe->hasalpha = true;
6905                                 break;
6906                         }
6907                 }
6908                 if (r_loadfog && skinframe->hasalpha)
6909                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6910         }
6911
6912         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6913         //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]);
6914
6915         return skinframe;
6916 }
6917
6918 skinframe_t *R_SkinFrame_LoadMissing(void)
6919 {
6920         skinframe_t *skinframe;
6921
6922         if (cls.state == ca_dedicated)
6923                 return NULL;
6924
6925         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6926         skinframe->stain = NULL;
6927         skinframe->merged = NULL;
6928         skinframe->base = NULL;
6929         skinframe->pants = NULL;
6930         skinframe->shirt = NULL;
6931         skinframe->nmap = NULL;
6932         skinframe->gloss = NULL;
6933         skinframe->glow = NULL;
6934         skinframe->fog = NULL;
6935         skinframe->reflect = NULL;
6936         skinframe->hasalpha = false;
6937
6938         skinframe->avgcolor[0] = rand() / RAND_MAX;
6939         skinframe->avgcolor[1] = rand() / RAND_MAX;
6940         skinframe->avgcolor[2] = rand() / RAND_MAX;
6941         skinframe->avgcolor[3] = 1;
6942
6943         return skinframe;
6944 }
6945
6946 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6947 typedef struct suffixinfo_s
6948 {
6949         const char *suffix;
6950         qboolean flipx, flipy, flipdiagonal;
6951 }
6952 suffixinfo_t;
6953 static suffixinfo_t suffix[3][6] =
6954 {
6955         {
6956                 {"px",   false, false, false},
6957                 {"nx",   false, false, false},
6958                 {"py",   false, false, false},
6959                 {"ny",   false, false, false},
6960                 {"pz",   false, false, false},
6961                 {"nz",   false, false, false}
6962         },
6963         {
6964                 {"posx", false, false, false},
6965                 {"negx", false, false, false},
6966                 {"posy", false, false, false},
6967                 {"negy", false, false, false},
6968                 {"posz", false, false, false},
6969                 {"negz", false, false, false}
6970         },
6971         {
6972                 {"rt",    true, false,  true},
6973                 {"lf",   false,  true,  true},
6974                 {"ft",    true,  true, false},
6975                 {"bk",   false, false, false},
6976                 {"up",    true, false,  true},
6977                 {"dn",    true, false,  true}
6978         }
6979 };
6980
6981 static int componentorder[4] = {0, 1, 2, 3};
6982
6983 rtexture_t *R_LoadCubemap(const char *basename)
6984 {
6985         int i, j, cubemapsize;
6986         unsigned char *cubemappixels, *image_buffer;
6987         rtexture_t *cubemaptexture;
6988         char name[256];
6989         // must start 0 so the first loadimagepixels has no requested width/height
6990         cubemapsize = 0;
6991         cubemappixels = NULL;
6992         cubemaptexture = NULL;
6993         // keep trying different suffix groups (posx, px, rt) until one loads
6994         for (j = 0;j < 3 && !cubemappixels;j++)
6995         {
6996                 // load the 6 images in the suffix group
6997                 for (i = 0;i < 6;i++)
6998                 {
6999                         // generate an image name based on the base and and suffix
7000                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
7001                         // load it
7002                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
7003                         {
7004                                 // an image loaded, make sure width and height are equal
7005                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
7006                                 {
7007                                         // if this is the first image to load successfully, allocate the cubemap memory
7008                                         if (!cubemappixels && image_width >= 1)
7009                                         {
7010                                                 cubemapsize = image_width;
7011                                                 // note this clears to black, so unavailable sides are black
7012                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7013                                         }
7014                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7015                                         if (cubemappixels)
7016                                                 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);
7017                                 }
7018                                 else
7019                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7020                                 // free the image
7021                                 Mem_Free(image_buffer);
7022                         }
7023                 }
7024         }
7025         // if a cubemap loaded, upload it
7026         if (cubemappixels)
7027         {
7028                 if (developer_loading.integer)
7029                         Con_Printf("loading cubemap \"%s\"\n", basename);
7030
7031                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7032                 Mem_Free(cubemappixels);
7033         }
7034         else
7035         {
7036                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7037                 if (developer_loading.integer)
7038                 {
7039                         Con_Printf("(tried tried images ");
7040                         for (j = 0;j < 3;j++)
7041                                 for (i = 0;i < 6;i++)
7042                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7043                         Con_Print(" and was unable to find any of them).\n");
7044                 }
7045         }
7046         return cubemaptexture;
7047 }
7048
7049 rtexture_t *R_GetCubemap(const char *basename)
7050 {
7051         int i;
7052         for (i = 0;i < r_texture_numcubemaps;i++)
7053                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7054                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7055         if (i >= MAX_CUBEMAPS)
7056                 return r_texture_whitecube;
7057         r_texture_numcubemaps++;
7058         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7059         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7060         return r_texture_cubemaps[i].texture;
7061 }
7062
7063 void R_FreeCubemaps(void)
7064 {
7065         int i;
7066         for (i = 0;i < r_texture_numcubemaps;i++)
7067         {
7068                 if (developer_loading.integer)
7069                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7070                 if (r_texture_cubemaps[i].texture)
7071                         R_FreeTexture(r_texture_cubemaps[i].texture);
7072         }
7073         r_texture_numcubemaps = 0;
7074 }
7075
7076 void R_Main_FreeViewCache(void)
7077 {
7078         if (r_refdef.viewcache.entityvisible)
7079                 Mem_Free(r_refdef.viewcache.entityvisible);
7080         if (r_refdef.viewcache.world_pvsbits)
7081                 Mem_Free(r_refdef.viewcache.world_pvsbits);
7082         if (r_refdef.viewcache.world_leafvisible)
7083                 Mem_Free(r_refdef.viewcache.world_leafvisible);
7084         if (r_refdef.viewcache.world_surfacevisible)
7085                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7086         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7087 }
7088
7089 void R_Main_ResizeViewCache(void)
7090 {
7091         int numentities = r_refdef.scene.numentities;
7092         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7093         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7094         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7095         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7096         if (r_refdef.viewcache.maxentities < numentities)
7097         {
7098                 r_refdef.viewcache.maxentities = numentities;
7099                 if (r_refdef.viewcache.entityvisible)
7100                         Mem_Free(r_refdef.viewcache.entityvisible);
7101                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7102         }
7103         if (r_refdef.viewcache.world_numclusters != numclusters)
7104         {
7105                 r_refdef.viewcache.world_numclusters = numclusters;
7106                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7107                 if (r_refdef.viewcache.world_pvsbits)
7108                         Mem_Free(r_refdef.viewcache.world_pvsbits);
7109                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7110         }
7111         if (r_refdef.viewcache.world_numleafs != numleafs)
7112         {
7113                 r_refdef.viewcache.world_numleafs = numleafs;
7114                 if (r_refdef.viewcache.world_leafvisible)
7115                         Mem_Free(r_refdef.viewcache.world_leafvisible);
7116                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7117         }
7118         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7119         {
7120                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7121                 if (r_refdef.viewcache.world_surfacevisible)
7122                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
7123                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7124         }
7125 }
7126
7127 extern rtexture_t *loadingscreentexture;
7128 void gl_main_start(void)
7129 {
7130         loadingscreentexture = NULL;
7131         r_texture_blanknormalmap = NULL;
7132         r_texture_white = NULL;
7133         r_texture_grey128 = NULL;
7134         r_texture_black = NULL;
7135         r_texture_whitecube = NULL;
7136         r_texture_normalizationcube = NULL;
7137         r_texture_fogattenuation = NULL;
7138         r_texture_fogheighttexture = NULL;
7139         r_texture_gammaramps = NULL;
7140         r_texture_numcubemaps = 0;
7141
7142         r_loaddds = r_texture_dds_load.integer;
7143         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7144
7145         switch(vid.renderpath)
7146         {
7147         case RENDERPATH_GL20:
7148         case RENDERPATH_CGGL:
7149         case RENDERPATH_D3D9:
7150         case RENDERPATH_D3D10:
7151         case RENDERPATH_D3D11:
7152                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7153                 Cvar_SetValueQuick(&gl_combine, 1);
7154                 Cvar_SetValueQuick(&r_glsl, 1);
7155                 r_loadnormalmap = true;
7156                 r_loadgloss = true;
7157                 r_loadfog = false;
7158                 break;
7159         case RENDERPATH_GL13:
7160                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7161                 Cvar_SetValueQuick(&gl_combine, 1);
7162                 Cvar_SetValueQuick(&r_glsl, 0);
7163                 r_loadnormalmap = false;
7164                 r_loadgloss = false;
7165                 r_loadfog = true;
7166                 break;
7167         case RENDERPATH_GL11:
7168                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7169                 Cvar_SetValueQuick(&gl_combine, 0);
7170                 Cvar_SetValueQuick(&r_glsl, 0);
7171                 r_loadnormalmap = false;
7172                 r_loadgloss = false;
7173                 r_loadfog = true;
7174                 break;
7175         }
7176
7177         R_AnimCache_Free();
7178         R_FrameData_Reset();
7179
7180         r_numqueries = 0;
7181         r_maxqueries = 0;
7182         memset(r_queries, 0, sizeof(r_queries));
7183
7184         r_qwskincache = NULL;
7185         r_qwskincache_size = 0;
7186
7187         // set up r_skinframe loading system for textures
7188         memset(&r_skinframe, 0, sizeof(r_skinframe));
7189         r_skinframe.loadsequence = 1;
7190         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7191
7192         r_main_texturepool = R_AllocTexturePool();
7193         R_BuildBlankTextures();
7194         R_BuildNoTexture();
7195         if (vid.support.arb_texture_cube_map)
7196         {
7197                 R_BuildWhiteCube();
7198                 R_BuildNormalizationCube();
7199         }
7200         r_texture_fogattenuation = NULL;
7201         r_texture_fogheighttexture = NULL;
7202         r_texture_gammaramps = NULL;
7203         //r_texture_fogintensity = NULL;
7204         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7205         memset(&r_waterstate, 0, sizeof(r_waterstate));
7206         r_glsl_permutation = NULL;
7207         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7208         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7209         glslshaderstring = NULL;
7210 #ifdef SUPPORTCG
7211         r_cg_permutation = NULL;
7212         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7213         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7214         cgshaderstring = NULL;
7215 #endif
7216 #ifdef SUPPORTD3D
7217         r_hlsl_permutation = NULL;
7218         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7219         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7220         hlslshaderstring = NULL;
7221 #endif
7222         memset(&r_svbsp, 0, sizeof (r_svbsp));
7223
7224         r_refdef.fogmasktable_density = 0;
7225 }
7226
7227 void gl_main_shutdown(void)
7228 {
7229         R_AnimCache_Free();
7230         R_FrameData_Reset();
7231
7232         R_Main_FreeViewCache();
7233
7234         switch(vid.renderpath)
7235         {
7236         case RENDERPATH_GL11:
7237         case RENDERPATH_GL13:
7238         case RENDERPATH_GL20:
7239         case RENDERPATH_CGGL:
7240                 if (r_maxqueries)
7241                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7242                 break;
7243         case RENDERPATH_D3D9:
7244                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7245                 break;
7246         case RENDERPATH_D3D10:
7247                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7248                 break;
7249         case RENDERPATH_D3D11:
7250                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7251                 break;
7252         }
7253
7254         r_numqueries = 0;
7255         r_maxqueries = 0;
7256         memset(r_queries, 0, sizeof(r_queries));
7257
7258         r_qwskincache = NULL;
7259         r_qwskincache_size = 0;
7260
7261         // clear out the r_skinframe state
7262         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7263         memset(&r_skinframe, 0, sizeof(r_skinframe));
7264
7265         if (r_svbsp.nodes)
7266                 Mem_Free(r_svbsp.nodes);
7267         memset(&r_svbsp, 0, sizeof (r_svbsp));
7268         R_FreeTexturePool(&r_main_texturepool);
7269         loadingscreentexture = NULL;
7270         r_texture_blanknormalmap = NULL;
7271         r_texture_white = NULL;
7272         r_texture_grey128 = NULL;
7273         r_texture_black = NULL;
7274         r_texture_whitecube = NULL;
7275         r_texture_normalizationcube = NULL;
7276         r_texture_fogattenuation = NULL;
7277         r_texture_fogheighttexture = NULL;
7278         r_texture_gammaramps = NULL;
7279         r_texture_numcubemaps = 0;
7280         //r_texture_fogintensity = NULL;
7281         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7282         memset(&r_waterstate, 0, sizeof(r_waterstate));
7283         R_GLSL_Restart_f();
7284 }
7285
7286 extern void CL_ParseEntityLump(char *entitystring);
7287 void gl_main_newmap(void)
7288 {
7289         // FIXME: move this code to client
7290         char *entities, entname[MAX_QPATH];
7291         if (r_qwskincache)
7292                 Mem_Free(r_qwskincache);
7293         r_qwskincache = NULL;
7294         r_qwskincache_size = 0;
7295         if (cl.worldmodel)
7296         {
7297                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7298                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7299                 {
7300                         CL_ParseEntityLump(entities);
7301                         Mem_Free(entities);
7302                         return;
7303                 }
7304                 if (cl.worldmodel->brush.entities)
7305                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7306         }
7307         R_Main_FreeViewCache();
7308
7309         R_FrameData_Reset();
7310 }
7311
7312 void GL_Main_Init(void)
7313 {
7314         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7315
7316         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7317         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7318         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7319         if (gamemode == GAME_NEHAHRA)
7320         {
7321                 Cvar_RegisterVariable (&gl_fogenable);
7322                 Cvar_RegisterVariable (&gl_fogdensity);
7323                 Cvar_RegisterVariable (&gl_fogred);
7324                 Cvar_RegisterVariable (&gl_foggreen);
7325                 Cvar_RegisterVariable (&gl_fogblue);
7326                 Cvar_RegisterVariable (&gl_fogstart);
7327                 Cvar_RegisterVariable (&gl_fogend);
7328                 Cvar_RegisterVariable (&gl_skyclip);
7329         }
7330         Cvar_RegisterVariable(&r_motionblur);
7331         Cvar_RegisterVariable(&r_motionblur_maxblur);
7332         Cvar_RegisterVariable(&r_motionblur_bmin);
7333         Cvar_RegisterVariable(&r_motionblur_vmin);
7334         Cvar_RegisterVariable(&r_motionblur_vmax);
7335         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7336         Cvar_RegisterVariable(&r_motionblur_randomize);
7337         Cvar_RegisterVariable(&r_damageblur);
7338         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7339         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7340         Cvar_RegisterVariable(&r_equalize_entities_by);
7341         Cvar_RegisterVariable(&r_equalize_entities_to);
7342         Cvar_RegisterVariable(&r_depthfirst);
7343         Cvar_RegisterVariable(&r_useinfinitefarclip);
7344         Cvar_RegisterVariable(&r_farclip_base);
7345         Cvar_RegisterVariable(&r_farclip_world);
7346         Cvar_RegisterVariable(&r_nearclip);
7347         Cvar_RegisterVariable(&r_showbboxes);
7348         Cvar_RegisterVariable(&r_showsurfaces);
7349         Cvar_RegisterVariable(&r_showtris);
7350         Cvar_RegisterVariable(&r_shownormals);
7351         Cvar_RegisterVariable(&r_showlighting);
7352         Cvar_RegisterVariable(&r_showshadowvolumes);
7353         Cvar_RegisterVariable(&r_showcollisionbrushes);
7354         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7355         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7356         Cvar_RegisterVariable(&r_showdisabledepthtest);
7357         Cvar_RegisterVariable(&r_drawportals);
7358         Cvar_RegisterVariable(&r_drawentities);
7359         Cvar_RegisterVariable(&r_draw2d);
7360         Cvar_RegisterVariable(&r_drawworld);
7361         Cvar_RegisterVariable(&r_cullentities_trace);
7362         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7363         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7364         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7365         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7366         Cvar_RegisterVariable(&r_drawviewmodel);
7367         Cvar_RegisterVariable(&r_drawexteriormodel);
7368         Cvar_RegisterVariable(&r_speeds);
7369         Cvar_RegisterVariable(&r_fullbrights);
7370         Cvar_RegisterVariable(&r_wateralpha);
7371         Cvar_RegisterVariable(&r_dynamic);
7372         Cvar_RegisterVariable(&r_fakelight);
7373         Cvar_RegisterVariable(&r_fakelight_intensity);
7374         Cvar_RegisterVariable(&r_fullbright);
7375         Cvar_RegisterVariable(&r_shadows);
7376         Cvar_RegisterVariable(&r_shadows_darken);
7377         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7378         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7379         Cvar_RegisterVariable(&r_shadows_throwdistance);
7380         Cvar_RegisterVariable(&r_shadows_throwdirection);
7381         Cvar_RegisterVariable(&r_shadows_focus);
7382         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7383         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7384         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7385         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7386         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7387         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7388         Cvar_RegisterVariable(&r_fog_exp2);
7389         Cvar_RegisterVariable(&r_drawfog);
7390         Cvar_RegisterVariable(&r_transparentdepthmasking);
7391         Cvar_RegisterVariable(&r_texture_dds_load);
7392         Cvar_RegisterVariable(&r_texture_dds_save);
7393         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7394         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7395         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7396         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7397         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7398         Cvar_RegisterVariable(&r_textureunits);
7399         Cvar_RegisterVariable(&gl_combine);
7400         Cvar_RegisterVariable(&r_glsl);
7401         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7402         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7403         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7404         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7405         Cvar_RegisterVariable(&r_glsl_postprocess);
7406         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7407         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7408         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7409         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7410         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
7411         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
7412         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
7413         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
7414
7415         Cvar_RegisterVariable(&r_water);
7416         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7417         Cvar_RegisterVariable(&r_water_clippingplanebias);
7418         Cvar_RegisterVariable(&r_water_refractdistort);
7419         Cvar_RegisterVariable(&r_water_reflectdistort);
7420         Cvar_RegisterVariable(&r_water_scissormode);
7421         Cvar_RegisterVariable(&r_lerpsprites);
7422         Cvar_RegisterVariable(&r_lerpmodels);
7423         Cvar_RegisterVariable(&r_lerplightstyles);
7424         Cvar_RegisterVariable(&r_waterscroll);
7425         Cvar_RegisterVariable(&r_bloom);
7426         Cvar_RegisterVariable(&r_bloom_colorscale);
7427         Cvar_RegisterVariable(&r_bloom_brighten);
7428         Cvar_RegisterVariable(&r_bloom_blur);
7429         Cvar_RegisterVariable(&r_bloom_resolution);
7430         Cvar_RegisterVariable(&r_bloom_colorexponent);
7431         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7432         Cvar_RegisterVariable(&r_hdr);
7433         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7434         Cvar_RegisterVariable(&r_hdr_glowintensity);
7435         Cvar_RegisterVariable(&r_hdr_range);
7436         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7437         Cvar_RegisterVariable(&developer_texturelogging);
7438         Cvar_RegisterVariable(&gl_lightmaps);
7439         Cvar_RegisterVariable(&r_test);
7440         Cvar_RegisterVariable(&r_glsl_saturation);
7441         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7442         Cvar_RegisterVariable(&r_framedatasize);
7443         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7444                 Cvar_SetValue("r_fullbrights", 0);
7445         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7446
7447         Cvar_RegisterVariable(&r_track_sprites);
7448         Cvar_RegisterVariable(&r_track_sprites_flags);
7449         Cvar_RegisterVariable(&r_track_sprites_scalew);
7450         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7451         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7452         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7453 }
7454
7455 extern void R_Textures_Init(void);
7456 extern void GL_Draw_Init(void);
7457 extern void GL_Main_Init(void);
7458 extern void R_Shadow_Init(void);
7459 extern void R_Sky_Init(void);
7460 extern void GL_Surf_Init(void);
7461 extern void R_Particles_Init(void);
7462 extern void R_Explosion_Init(void);
7463 extern void gl_backend_init(void);
7464 extern void Sbar_Init(void);
7465 extern void R_LightningBeams_Init(void);
7466 extern void Mod_RenderInit(void);
7467 extern void Font_Init(void);
7468
7469 void Render_Init(void)
7470 {
7471         gl_backend_init();
7472         R_Textures_Init();
7473         GL_Main_Init();
7474         Font_Init();
7475         GL_Draw_Init();
7476         R_Shadow_Init();
7477         R_Sky_Init();
7478         GL_Surf_Init();
7479         Sbar_Init();
7480         R_Particles_Init();
7481         R_Explosion_Init();
7482         R_LightningBeams_Init();
7483         Mod_RenderInit();
7484 }
7485
7486 /*
7487 ===============
7488 GL_Init
7489 ===============
7490 */
7491 extern char *ENGINE_EXTENSIONS;
7492 void GL_Init (void)
7493 {
7494         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7495         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7496         gl_version = (const char *)qglGetString(GL_VERSION);
7497         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7498
7499         if (!gl_extensions)
7500                 gl_extensions = "";
7501         if (!gl_platformextensions)
7502                 gl_platformextensions = "";
7503
7504         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7505         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7506         Con_Printf("GL_VERSION: %s\n", gl_version);
7507         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7508         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7509
7510         VID_CheckExtensions();
7511
7512         // LordHavoc: report supported extensions
7513         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7514
7515         // clear to black (loading plaque will be seen over this)
7516         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7517 }
7518
7519 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7520 {
7521         int i;
7522         mplane_t *p;
7523         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7524         {
7525                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7526                 if (i == 4)
7527                         continue;
7528                 p = r_refdef.view.frustum + i;
7529                 switch(p->signbits)
7530                 {
7531                 default:
7532                 case 0:
7533                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7534                                 return true;
7535                         break;
7536                 case 1:
7537                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7538                                 return true;
7539                         break;
7540                 case 2:
7541                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7542                                 return true;
7543                         break;
7544                 case 3:
7545                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7546                                 return true;
7547                         break;
7548                 case 4:
7549                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7550                                 return true;
7551                         break;
7552                 case 5:
7553                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7554                                 return true;
7555                         break;
7556                 case 6:
7557                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7558                                 return true;
7559                         break;
7560                 case 7:
7561                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7562                                 return true;
7563                         break;
7564                 }
7565         }
7566         return false;
7567 }
7568
7569 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7570 {
7571         int i;
7572         const mplane_t *p;
7573         for (i = 0;i < numplanes;i++)
7574         {
7575                 p = planes + i;
7576                 switch(p->signbits)
7577                 {
7578                 default:
7579                 case 0:
7580                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7581                                 return true;
7582                         break;
7583                 case 1:
7584                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7585                                 return true;
7586                         break;
7587                 case 2:
7588                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7589                                 return true;
7590                         break;
7591                 case 3:
7592                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7593                                 return true;
7594                         break;
7595                 case 4:
7596                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7597                                 return true;
7598                         break;
7599                 case 5:
7600                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7601                                 return true;
7602                         break;
7603                 case 6:
7604                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7605                                 return true;
7606                         break;
7607                 case 7:
7608                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7609                                 return true;
7610                         break;
7611                 }
7612         }
7613         return false;
7614 }
7615
7616 //==================================================================================
7617
7618 // LordHavoc: this stores temporary data used within the same frame
7619
7620 qboolean r_framedata_failed;
7621 static size_t r_framedata_size;
7622 static size_t r_framedata_current;
7623 static void *r_framedata_base;
7624
7625 void R_FrameData_Reset(void)
7626 {
7627         if (r_framedata_base)
7628                 Mem_Free(r_framedata_base);
7629         r_framedata_base = NULL;
7630         r_framedata_size = 0;
7631         r_framedata_current = 0;
7632         r_framedata_failed = false;
7633 }
7634
7635 void R_FrameData_NewFrame(void)
7636 {
7637         size_t wantedsize;
7638         if (r_framedata_failed)
7639                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7640         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7641         wantedsize = bound(65536, wantedsize, 128*1024*1024);
7642         if (r_framedata_size != wantedsize)
7643         {
7644                 r_framedata_size = wantedsize;
7645                 if (r_framedata_base)
7646                         Mem_Free(r_framedata_base);
7647                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7648         }
7649         r_framedata_current = 0;
7650         r_framedata_failed = false;
7651 }
7652
7653 void *R_FrameData_Alloc(size_t size)
7654 {
7655         void *data;
7656
7657         // align to 16 byte boundary
7658         size = (size + 15) & ~15;
7659         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7660         r_framedata_current += size;
7661
7662         // check overflow
7663         if (r_framedata_current > r_framedata_size)
7664                 r_framedata_failed = true;
7665
7666         // return NULL on everything after a failure
7667         if (r_framedata_failed)
7668                 return NULL;
7669
7670         return data;
7671 }
7672
7673 void *R_FrameData_Store(size_t size, void *data)
7674 {
7675         void *d = R_FrameData_Alloc(size);
7676         if (d)
7677                 memcpy(d, data, size);
7678         return d;
7679 }
7680
7681 //==================================================================================
7682
7683 // LordHavoc: animcache originally written by Echon, rewritten since then
7684
7685 /**
7686  * Animation cache prevents re-generating mesh data for an animated model
7687  * multiple times in one frame for lighting, shadowing, reflections, etc.
7688  */
7689
7690 void R_AnimCache_Free(void)
7691 {
7692 }
7693
7694 void R_AnimCache_ClearCache(void)
7695 {
7696         int i;
7697         entity_render_t *ent;
7698
7699         for (i = 0;i < r_refdef.scene.numentities;i++)
7700         {
7701                 ent = r_refdef.scene.entities[i];
7702                 ent->animcache_vertex3f = NULL;
7703                 ent->animcache_normal3f = NULL;
7704                 ent->animcache_svector3f = NULL;
7705                 ent->animcache_tvector3f = NULL;
7706                 ent->animcache_vertexposition = NULL;
7707                 ent->animcache_vertexmesh = NULL;
7708                 ent->animcache_vertexpositionbuffer = NULL;
7709                 ent->animcache_vertexmeshbuffer = NULL;
7710         }
7711 }
7712
7713 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7714 {
7715         int i;
7716
7717         // identical memory layout, so no need to allocate...
7718         // this also provides the vertexposition structure to everything, e.g.
7719         // depth masked rendering currently uses it even if having separate
7720         // arrays
7721         // NOTE: get rid of this optimization if changing it to e.g. 4f
7722         ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7723
7724         // TODO:
7725         // get rid of following uses of VERTEXPOSITION, change to the array:
7726         // R_DrawTextureSurfaceList_Sky if skyrendermasked
7727         // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7728         // R_DrawTextureSurfaceList_DepthOnly
7729         // R_Q1BSP_DrawShadowMap
7730
7731         switch(vid.renderpath)
7732         {
7733         case RENDERPATH_GL20:
7734         case RENDERPATH_CGGL:
7735                 // need the meshbuffers if !gl_mesh_separatearrays.integer
7736                 if (gl_mesh_separatearrays.integer)
7737                         return;
7738                 break;
7739         case RENDERPATH_D3D9:
7740         case RENDERPATH_D3D10:
7741         case RENDERPATH_D3D11:
7742                 // always need the meshbuffers
7743                 break;
7744         case RENDERPATH_GL13:
7745         case RENDERPATH_GL11:
7746                 // never need the meshbuffers
7747                 return;
7748         }
7749
7750         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7751                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7752         /*
7753         if (!ent->animcache_vertexposition)
7754                 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7755         */
7756         if (ent->animcache_vertexposition)
7757         {
7758                 /*
7759                 for (i = 0;i < numvertices;i++)
7760                         memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7761                 */
7762                 // TODO: upload vertex buffer?
7763         }
7764         if (ent->animcache_vertexmesh)
7765         {
7766                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7767                 for (i = 0;i < numvertices;i++)
7768                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7769                 if (ent->animcache_svector3f)
7770                         for (i = 0;i < numvertices;i++)
7771                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7772                 if (ent->animcache_tvector3f)
7773                         for (i = 0;i < numvertices;i++)
7774                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7775                 if (ent->animcache_normal3f)
7776                         for (i = 0;i < numvertices;i++)
7777                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7778                 // TODO: upload vertex buffer?
7779         }
7780 }
7781
7782 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7783 {
7784         dp_model_t *model = ent->model;
7785         int numvertices;
7786         // see if it's already cached this frame
7787         if (ent->animcache_vertex3f)
7788         {
7789                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7790                 if (wantnormals || wanttangents)
7791                 {
7792                         if (ent->animcache_normal3f)
7793                                 wantnormals = false;
7794                         if (ent->animcache_svector3f)
7795                                 wanttangents = false;
7796                         if (wantnormals || wanttangents)
7797                         {
7798                                 numvertices = model->surfmesh.num_vertices;
7799                                 if (wantnormals)
7800                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7801                                 if (wanttangents)
7802                                 {
7803                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7804                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7805                                 }
7806                                 if (!r_framedata_failed)
7807                                 {
7808                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7809                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7810                                 }
7811                         }
7812                 }
7813         }
7814         else
7815         {
7816                 // see if this ent is worth caching
7817                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7818                         return false;
7819                 // get some memory for this entity and generate mesh data
7820                 numvertices = model->surfmesh.num_vertices;
7821                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7822                 if (wantnormals)
7823                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7824                 if (wanttangents)
7825                 {
7826                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7827                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7828                 }
7829                 if (!r_framedata_failed)
7830                 {
7831                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7832                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7833                 }
7834         }
7835         return !r_framedata_failed;
7836 }
7837
7838 void R_AnimCache_CacheVisibleEntities(void)
7839 {
7840         int i;
7841         qboolean wantnormals = true;
7842         qboolean wanttangents = !r_showsurfaces.integer;
7843
7844         switch(vid.renderpath)
7845         {
7846         case RENDERPATH_GL20:
7847         case RENDERPATH_CGGL:
7848         case RENDERPATH_D3D9:
7849         case RENDERPATH_D3D10:
7850         case RENDERPATH_D3D11:
7851                 break;
7852         case RENDERPATH_GL13:
7853         case RENDERPATH_GL11:
7854                 wanttangents = false;
7855                 break;
7856         }
7857
7858         if (r_shownormals.integer)
7859                 wanttangents = wantnormals = true;
7860
7861         // TODO: thread this
7862         // NOTE: R_PrepareRTLights() also caches entities
7863
7864         for (i = 0;i < r_refdef.scene.numentities;i++)
7865                 if (r_refdef.viewcache.entityvisible[i])
7866                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7867 }
7868
7869 //==================================================================================
7870
7871 static void R_View_UpdateEntityLighting (void)
7872 {
7873         int i;
7874         entity_render_t *ent;
7875         vec3_t tempdiffusenormal, avg;
7876         vec_t f, fa, fd, fdd;
7877         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7878
7879         for (i = 0;i < r_refdef.scene.numentities;i++)
7880         {
7881                 ent = r_refdef.scene.entities[i];
7882
7883                 // skip unseen models
7884                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7885                         continue;
7886
7887                 // skip bsp models
7888                 if (ent->model && ent->model->brush.num_leafs)
7889                 {
7890                         // TODO: use modellight for r_ambient settings on world?
7891                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7892                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7893                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7894                         continue;
7895                 }
7896
7897                 // fetch the lighting from the worldmodel data
7898                 VectorClear(ent->modellight_ambient);
7899                 VectorClear(ent->modellight_diffuse);
7900                 VectorClear(tempdiffusenormal);
7901                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7902                 {
7903                         vec3_t org;
7904                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7905
7906                         // complete lightning for lit sprites
7907                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7908                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7909                         {
7910                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7911                                         org[2] = org[2] + r_overheadsprites_pushback.value;
7912                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7913                         }
7914                         else
7915                                 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7916
7917                         if(ent->flags & RENDER_EQUALIZE)
7918                         {
7919                                 // first fix up ambient lighting...
7920                                 if(r_equalize_entities_minambient.value > 0)
7921                                 {
7922                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7923                                         if(fd > 0)
7924                                         {
7925                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7926                                                 if(fa < r_equalize_entities_minambient.value * fd)
7927                                                 {
7928                                                         // solve:
7929                                                         //   fa'/fd' = minambient
7930                                                         //   fa'+0.25*fd' = fa+0.25*fd
7931                                                         //   ...
7932                                                         //   fa' = fd' * minambient
7933                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7934                                                         //   ...
7935                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7936                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7937                                                         //   ...
7938                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7939                                                         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
7940                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7941                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7942                                                 }
7943                                         }
7944                                 }
7945
7946                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7947                                 {
7948                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
7949                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7950                                         f = fa + 0.25 * fd;
7951                                         if(f > 0)
7952                                         {
7953                                                 // adjust brightness and saturation to target
7954                                                 avg[0] = avg[1] = avg[2] = fa / f;
7955                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
7956                                                 avg[0] = avg[1] = avg[2] = fd / f;
7957                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
7958                                         }
7959                                 }
7960                         }
7961                 }
7962                 else // highly rare
7963                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7964
7965                 // move the light direction into modelspace coordinates for lighting code
7966                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7967                 if(VectorLength2(ent->modellight_lightdir) == 0)
7968                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7969                 VectorNormalize(ent->modellight_lightdir);
7970         }
7971 }
7972
7973 #define MAX_LINEOFSIGHTTRACES 64
7974
7975 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7976 {
7977         int i;
7978         vec3_t boxmins, boxmaxs;
7979         vec3_t start;
7980         vec3_t end;
7981         dp_model_t *model = r_refdef.scene.worldmodel;
7982
7983         if (!model || !model->brush.TraceLineOfSight)
7984                 return true;
7985
7986         // expand the box a little
7987         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7988         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7989         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7990         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7991         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7992         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7993
7994         // return true if eye is inside enlarged box
7995         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7996                 return true;
7997
7998         // try center
7999         VectorCopy(eye, start);
8000         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
8001         if (model->brush.TraceLineOfSight(model, start, end))
8002                 return true;
8003
8004         // try various random positions
8005         for (i = 0;i < numsamples;i++)
8006         {
8007                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
8008                 if (model->brush.TraceLineOfSight(model, start, end))
8009                         return true;
8010         }
8011
8012         return false;
8013 }
8014
8015
8016 static void R_View_UpdateEntityVisible (void)
8017 {
8018         int i;
8019         int renderimask;
8020         int samples;
8021         entity_render_t *ent;
8022
8023         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8024                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8025                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
8026                 :                                                          RENDER_EXTERIORMODEL;
8027         if (!r_drawviewmodel.integer)
8028                 renderimask |= RENDER_VIEWMODEL;
8029         if (!r_drawexteriormodel.integer)
8030                 renderimask |= RENDER_EXTERIORMODEL;
8031         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8032         {
8033                 // worldmodel can check visibility
8034                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8035                 for (i = 0;i < r_refdef.scene.numentities;i++)
8036                 {
8037                         ent = r_refdef.scene.entities[i];
8038                         if (!(ent->flags & renderimask))
8039                         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)))
8040                         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))
8041                                 r_refdef.viewcache.entityvisible[i] = true;
8042                 }
8043                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8044                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8045                 {
8046                         for (i = 0;i < r_refdef.scene.numentities;i++)
8047                         {
8048                                 ent = r_refdef.scene.entities[i];
8049                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8050                                 {
8051                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8052                                         if (samples < 0)
8053                                                 continue; // temp entities do pvs only
8054                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8055                                                 ent->last_trace_visibility = realtime;
8056                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8057                                                 r_refdef.viewcache.entityvisible[i] = 0;
8058                                 }
8059                         }
8060                 }
8061         }
8062         else
8063         {
8064                 // no worldmodel or it can't check visibility
8065                 for (i = 0;i < r_refdef.scene.numentities;i++)
8066                 {
8067                         ent = r_refdef.scene.entities[i];
8068                         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));
8069                 }
8070         }
8071 }
8072
8073 /// only used if skyrendermasked, and normally returns false
8074 int R_DrawBrushModelsSky (void)
8075 {
8076         int i, sky;
8077         entity_render_t *ent;
8078
8079         sky = false;
8080         for (i = 0;i < r_refdef.scene.numentities;i++)
8081         {
8082                 if (!r_refdef.viewcache.entityvisible[i])
8083                         continue;
8084                 ent = r_refdef.scene.entities[i];
8085                 if (!ent->model || !ent->model->DrawSky)
8086                         continue;
8087                 ent->model->DrawSky(ent);
8088                 sky = true;
8089         }
8090         return sky;
8091 }
8092
8093 static void R_DrawNoModel(entity_render_t *ent);
8094 static void R_DrawModels(void)
8095 {
8096         int i;
8097         entity_render_t *ent;
8098
8099         for (i = 0;i < r_refdef.scene.numentities;i++)
8100         {
8101                 if (!r_refdef.viewcache.entityvisible[i])
8102                         continue;
8103                 ent = r_refdef.scene.entities[i];
8104                 r_refdef.stats.entities++;
8105                 if (ent->model && ent->model->Draw != NULL)
8106                         ent->model->Draw(ent);
8107                 else
8108                         R_DrawNoModel(ent);
8109         }
8110 }
8111
8112 static void R_DrawModelsDepth(void)
8113 {
8114         int i;
8115         entity_render_t *ent;
8116
8117         for (i = 0;i < r_refdef.scene.numentities;i++)
8118         {
8119                 if (!r_refdef.viewcache.entityvisible[i])
8120                         continue;
8121                 ent = r_refdef.scene.entities[i];
8122                 if (ent->model && ent->model->DrawDepth != NULL)
8123                         ent->model->DrawDepth(ent);
8124         }
8125 }
8126
8127 static void R_DrawModelsDebug(void)
8128 {
8129         int i;
8130         entity_render_t *ent;
8131
8132         for (i = 0;i < r_refdef.scene.numentities;i++)
8133         {
8134                 if (!r_refdef.viewcache.entityvisible[i])
8135                         continue;
8136                 ent = r_refdef.scene.entities[i];
8137                 if (ent->model && ent->model->DrawDebug != NULL)
8138                         ent->model->DrawDebug(ent);
8139         }
8140 }
8141
8142 static void R_DrawModelsAddWaterPlanes(void)
8143 {
8144         int i;
8145         entity_render_t *ent;
8146
8147         for (i = 0;i < r_refdef.scene.numentities;i++)
8148         {
8149                 if (!r_refdef.viewcache.entityvisible[i])
8150                         continue;
8151                 ent = r_refdef.scene.entities[i];
8152                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8153                         ent->model->DrawAddWaterPlanes(ent);
8154         }
8155 }
8156
8157 static void R_View_SetFrustum(const int *scissor)
8158 {
8159         int i;
8160         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8161         vec3_t forward, left, up, origin, v;
8162
8163         if(scissor)
8164         {
8165                 // flipped x coordinates (because x points left here)
8166                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8167                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8168
8169                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8170                 switch(vid.renderpath)
8171                 {
8172                         case RENDERPATH_D3D9:
8173                         case RENDERPATH_D3D10:
8174                         case RENDERPATH_D3D11:
8175                                 // non-flipped y coordinates
8176                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8177                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8178                                 break;
8179                         case RENDERPATH_GL11:
8180                         case RENDERPATH_GL13:
8181                         case RENDERPATH_GL20:
8182                         case RENDERPATH_CGGL:
8183                                 // non-flipped y coordinates
8184                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8185                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8186                                 break;
8187                 }
8188         }
8189
8190         // we can't trust r_refdef.view.forward and friends in reflected scenes
8191         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8192
8193 #if 0
8194         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8195         r_refdef.view.frustum[0].normal[1] = 0 - 0;
8196         r_refdef.view.frustum[0].normal[2] = -1 - 0;
8197         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8198         r_refdef.view.frustum[1].normal[1] = 0 + 0;
8199         r_refdef.view.frustum[1].normal[2] = -1 + 0;
8200         r_refdef.view.frustum[2].normal[0] = 0 - 0;
8201         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8202         r_refdef.view.frustum[2].normal[2] = -1 - 0;
8203         r_refdef.view.frustum[3].normal[0] = 0 + 0;
8204         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8205         r_refdef.view.frustum[3].normal[2] = -1 + 0;
8206 #endif
8207
8208 #if 0
8209         zNear = r_refdef.nearclip;
8210         nudge = 1.0 - 1.0 / (1<<23);
8211         r_refdef.view.frustum[4].normal[0] = 0 - 0;
8212         r_refdef.view.frustum[4].normal[1] = 0 - 0;
8213         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8214         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8215         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8216         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8217         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8218         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8219 #endif
8220
8221
8222
8223 #if 0
8224         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8225         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8226         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8227         r_refdef.view.frustum[0].dist = m[15] - m[12];
8228
8229         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8230         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8231         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8232         r_refdef.view.frustum[1].dist = m[15] + m[12];
8233
8234         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8235         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8236         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8237         r_refdef.view.frustum[2].dist = m[15] - m[13];
8238
8239         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8240         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8241         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8242         r_refdef.view.frustum[3].dist = m[15] + m[13];
8243
8244         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8245         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8246         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8247         r_refdef.view.frustum[4].dist = m[15] - m[14];
8248
8249         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8250         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8251         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8252         r_refdef.view.frustum[5].dist = m[15] + m[14];
8253 #endif
8254
8255         if (r_refdef.view.useperspective)
8256         {
8257                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8258                 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]);
8259                 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]);
8260                 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]);
8261                 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]);
8262
8263                 // then the normals from the corners relative to origin
8264                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8265                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8266                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8267                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8268
8269                 // in a NORMAL view, forward cross left == up
8270                 // in a REFLECTED view, forward cross left == down
8271                 // so our cross products above need to be adjusted for a left handed coordinate system
8272                 CrossProduct(forward, left, v);
8273                 if(DotProduct(v, up) < 0)
8274                 {
8275                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8276                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8277                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8278                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8279                 }
8280
8281                 // Leaving those out was a mistake, those were in the old code, and they
8282                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8283                 // I couldn't reproduce it after adding those normalizations. --blub
8284                 VectorNormalize(r_refdef.view.frustum[0].normal);
8285                 VectorNormalize(r_refdef.view.frustum[1].normal);
8286                 VectorNormalize(r_refdef.view.frustum[2].normal);
8287                 VectorNormalize(r_refdef.view.frustum[3].normal);
8288
8289                 // make the corners absolute
8290                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8291                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8292                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8293                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8294
8295                 // one more normal
8296                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8297
8298                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8299                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8300                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8301                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8302                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8303         }
8304         else
8305         {
8306                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8307                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8308                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8309                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8310                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8311                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8312                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8313                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8314                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8315                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8316         }
8317         r_refdef.view.numfrustumplanes = 5;
8318
8319         if (r_refdef.view.useclipplane)
8320         {
8321                 r_refdef.view.numfrustumplanes = 6;
8322                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8323         }
8324
8325         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8326                 PlaneClassify(r_refdef.view.frustum + i);
8327
8328         // LordHavoc: note to all quake engine coders, Quake had a special case
8329         // for 90 degrees which assumed a square view (wrong), so I removed it,
8330         // Quake2 has it disabled as well.
8331
8332         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8333         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8334         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8335         //PlaneClassify(&frustum[0]);
8336
8337         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8338         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8339         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8340         //PlaneClassify(&frustum[1]);
8341
8342         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8343         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8344         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8345         //PlaneClassify(&frustum[2]);
8346
8347         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8348         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8349         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8350         //PlaneClassify(&frustum[3]);
8351
8352         // nearclip plane
8353         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8354         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8355         //PlaneClassify(&frustum[4]);
8356 }
8357
8358 void R_View_UpdateWithScissor(const int *myscissor)
8359 {
8360         R_Main_ResizeViewCache();
8361         R_View_SetFrustum(myscissor);
8362         R_View_WorldVisibility(r_refdef.view.useclipplane);
8363         R_View_UpdateEntityVisible();
8364         R_View_UpdateEntityLighting();
8365 }
8366
8367 void R_View_Update(void)
8368 {
8369         R_Main_ResizeViewCache();
8370         R_View_SetFrustum(NULL);
8371         R_View_WorldVisibility(r_refdef.view.useclipplane);
8372         R_View_UpdateEntityVisible();
8373         R_View_UpdateEntityLighting();
8374 }
8375
8376 void R_SetupView(qboolean allowwaterclippingplane)
8377 {
8378         const float *customclipplane = NULL;
8379         float plane[4];
8380         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8381         {
8382                 // LordHavoc: couldn't figure out how to make this approach the
8383                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8384                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8385                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8386                         dist = r_refdef.view.clipplane.dist;
8387                 plane[0] = r_refdef.view.clipplane.normal[0];
8388                 plane[1] = r_refdef.view.clipplane.normal[1];
8389                 plane[2] = r_refdef.view.clipplane.normal[2];
8390                 plane[3] = dist;
8391                 customclipplane = plane;
8392         }
8393
8394         if (!r_refdef.view.useperspective)
8395                 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);
8396         else if (vid.stencil && r_useinfinitefarclip.integer)
8397                 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);
8398         else
8399                 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);
8400         R_SetViewport(&r_refdef.view.viewport);
8401 }
8402
8403 void R_EntityMatrix(const matrix4x4_t *matrix)
8404 {
8405         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8406         {
8407                 gl_modelmatrixchanged = false;
8408                 gl_modelmatrix = *matrix;
8409                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8410                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8411                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8412                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8413                 CHECKGLERROR
8414                 switch(vid.renderpath)
8415                 {
8416                 case RENDERPATH_D3D9:
8417 #ifdef SUPPORTD3D
8418                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8419                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8420 #endif
8421                         break;
8422                 case RENDERPATH_D3D10:
8423                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8424                         break;
8425                 case RENDERPATH_D3D11:
8426                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8427                         break;
8428                 case RENDERPATH_GL20:
8429                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8430                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8431                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8432                         break;
8433                 case RENDERPATH_CGGL:
8434 #ifdef SUPPORTCG
8435                         CHECKCGERROR
8436                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8437                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8438                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8439 #endif
8440                         break;
8441                 case RENDERPATH_GL13:
8442                 case RENDERPATH_GL11:
8443                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8444                         break;
8445                 }
8446         }
8447 }
8448
8449 void R_ResetViewRendering2D(void)
8450 {
8451         r_viewport_t viewport;
8452         DrawQ_Finish();
8453
8454         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8455         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);
8456         R_SetViewport(&viewport);
8457         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8458         GL_Color(1, 1, 1, 1);
8459         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8460         GL_BlendFunc(GL_ONE, GL_ZERO);
8461         GL_AlphaTest(false);
8462         GL_ScissorTest(false);
8463         GL_DepthMask(false);
8464         GL_DepthRange(0, 1);
8465         GL_DepthTest(false);
8466         GL_DepthFunc(GL_LEQUAL);
8467         R_EntityMatrix(&identitymatrix);
8468         R_Mesh_ResetTextureState();
8469         GL_PolygonOffset(0, 0);
8470         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8471         switch(vid.renderpath)
8472         {
8473         case RENDERPATH_GL11:
8474         case RENDERPATH_GL13:
8475         case RENDERPATH_GL20:
8476         case RENDERPATH_CGGL:
8477                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8478                 break;
8479         case RENDERPATH_D3D9:
8480         case RENDERPATH_D3D10:
8481         case RENDERPATH_D3D11:
8482                 break;
8483         }
8484         GL_CullFace(GL_NONE);
8485 }
8486
8487 void R_ResetViewRendering3D(void)
8488 {
8489         DrawQ_Finish();
8490
8491         R_SetupView(true);
8492         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8493         GL_Color(1, 1, 1, 1);
8494         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8495         GL_BlendFunc(GL_ONE, GL_ZERO);
8496         GL_AlphaTest(false);
8497         GL_ScissorTest(true);
8498         GL_DepthMask(true);
8499         GL_DepthRange(0, 1);
8500         GL_DepthTest(true);
8501         GL_DepthFunc(GL_LEQUAL);
8502         R_EntityMatrix(&identitymatrix);
8503         R_Mesh_ResetTextureState();
8504         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8505         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8506         switch(vid.renderpath)
8507         {
8508         case RENDERPATH_GL11:
8509         case RENDERPATH_GL13:
8510         case RENDERPATH_GL20:
8511         case RENDERPATH_CGGL:
8512                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8513                 break;
8514         case RENDERPATH_D3D9:
8515         case RENDERPATH_D3D10:
8516         case RENDERPATH_D3D11:
8517                 break;
8518         }
8519         GL_CullFace(r_refdef.view.cullface_back);
8520 }
8521
8522 /*
8523 ================
8524 R_RenderView_UpdateViewVectors
8525 ================
8526 */
8527 static void R_RenderView_UpdateViewVectors(void)
8528 {
8529         // break apart the view matrix into vectors for various purposes
8530         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8531         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8532         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8533         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8534         // make an inverted copy of the view matrix for tracking sprites
8535         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8536 }
8537
8538 void R_RenderScene(void);
8539 void R_RenderWaterPlanes(void);
8540
8541 static void R_Water_StartFrame(void)
8542 {
8543         int i;
8544         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8545         r_waterstate_waterplane_t *p;
8546
8547         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8548                 return;
8549
8550         switch(vid.renderpath)
8551         {
8552         case RENDERPATH_GL20:
8553         case RENDERPATH_CGGL:
8554         case RENDERPATH_D3D9:
8555         case RENDERPATH_D3D10:
8556         case RENDERPATH_D3D11:
8557                 break;
8558         case RENDERPATH_GL13:
8559         case RENDERPATH_GL11:
8560                 return;
8561         }
8562
8563         // set waterwidth and waterheight to the water resolution that will be
8564         // used (often less than the screen resolution for faster rendering)
8565         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8566         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8567
8568         // calculate desired texture sizes
8569         // can't use water if the card does not support the texture size
8570         if (!r_water.integer || r_showsurfaces.integer)
8571                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8572         else if (vid.support.arb_texture_non_power_of_two)
8573         {
8574                 texturewidth = waterwidth;
8575                 textureheight = waterheight;
8576                 camerawidth = waterwidth;
8577                 cameraheight = waterheight;
8578         }
8579         else
8580         {
8581                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8582                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8583                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8584                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8585         }
8586
8587         // allocate textures as needed
8588         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8589         {
8590                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8591                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8592                 {
8593                         if (p->texture_refraction)
8594                                 R_FreeTexture(p->texture_refraction);
8595                         p->texture_refraction = NULL;
8596                         if (p->texture_reflection)
8597                                 R_FreeTexture(p->texture_reflection);
8598                         p->texture_reflection = NULL;
8599                         if (p->texture_camera)
8600                                 R_FreeTexture(p->texture_camera);
8601                         p->texture_camera = NULL;
8602                 }
8603                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8604                 r_waterstate.texturewidth = texturewidth;
8605                 r_waterstate.textureheight = textureheight;
8606                 r_waterstate.camerawidth = camerawidth;
8607                 r_waterstate.cameraheight = cameraheight;
8608         }
8609
8610         if (r_waterstate.texturewidth)
8611         {
8612                 r_waterstate.enabled = true;
8613
8614                 // when doing a reduced render (HDR) we want to use a smaller area
8615                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8616                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8617
8618                 // set up variables that will be used in shader setup
8619                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8620                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8621                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8622                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8623         }
8624
8625         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8626         r_waterstate.numwaterplanes = 0;
8627 }
8628
8629 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8630 {
8631         int triangleindex, planeindex;
8632         const int *e;
8633         vec3_t vert[3];
8634         vec3_t normal;
8635         vec3_t center;
8636         mplane_t plane;
8637         r_waterstate_waterplane_t *p;
8638         texture_t *t = R_GetCurrentTexture(surface->texture);
8639
8640         // just use the first triangle with a valid normal for any decisions
8641         VectorClear(normal);
8642         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8643         {
8644                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8645                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8646                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8647                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8648                 if (VectorLength2(normal) >= 0.001)
8649                         break;
8650         }
8651
8652         VectorCopy(normal, plane.normal);
8653         VectorNormalize(plane.normal);
8654         plane.dist = DotProduct(vert[0], plane.normal);
8655         PlaneClassify(&plane);
8656         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8657         {
8658                 // skip backfaces (except if nocullface is set)
8659                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8660                         return;
8661                 VectorNegate(plane.normal, plane.normal);
8662                 plane.dist *= -1;
8663                 PlaneClassify(&plane);
8664         }
8665
8666
8667         // find a matching plane if there is one
8668         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8669                 if(p->camera_entity == t->camera_entity)
8670                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8671                                 break;
8672         if (planeindex >= r_waterstate.maxwaterplanes)
8673                 return; // nothing we can do, out of planes
8674
8675         // if this triangle does not fit any known plane rendered this frame, add one
8676         if (planeindex >= r_waterstate.numwaterplanes)
8677         {
8678                 // store the new plane
8679                 r_waterstate.numwaterplanes++;
8680                 p->plane = plane;
8681                 // clear materialflags and pvs
8682                 p->materialflags = 0;
8683                 p->pvsvalid = false;
8684                 p->camera_entity = t->camera_entity;
8685                 VectorCopy(surface->mins, p->mins);
8686                 VectorCopy(surface->maxs, p->maxs);
8687         }
8688         else
8689         {
8690                 // merge mins/maxs
8691                 p->mins[0] = min(p->mins[0], surface->mins[0]);
8692                 p->mins[1] = min(p->mins[1], surface->mins[1]);
8693                 p->mins[2] = min(p->mins[2], surface->mins[2]);
8694                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8695                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8696                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8697         }
8698         // merge this surface's materialflags into the waterplane
8699         p->materialflags |= t->currentmaterialflags;
8700         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8701         {
8702                 // merge this surface's PVS into the waterplane
8703                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8704                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8705                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8706                 {
8707                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8708                         p->pvsvalid = true;
8709                 }
8710         }
8711 }
8712
8713 static void R_Water_ProcessPlanes(void)
8714 {
8715         int myscissor[4];
8716         r_refdef_view_t originalview;
8717         r_refdef_view_t myview;
8718         int planeindex;
8719         r_waterstate_waterplane_t *p;
8720         vec3_t visorigin;
8721
8722         originalview = r_refdef.view;
8723
8724         // make sure enough textures are allocated
8725         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8726         {
8727                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8728                 {
8729                         if (!p->texture_refraction)
8730                                 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);
8731                         if (!p->texture_refraction)
8732                                 goto error;
8733                 }
8734                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8735                 {
8736                         if (!p->texture_camera)
8737                                 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);
8738                         if (!p->texture_camera)
8739                                 goto error;
8740                 }
8741
8742                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8743                 {
8744                         if (!p->texture_reflection)
8745                                 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);
8746                         if (!p->texture_reflection)
8747                                 goto error;
8748                 }
8749         }
8750
8751         // render views
8752         r_refdef.view = originalview;
8753         r_refdef.view.showdebug = false;
8754         r_refdef.view.width = r_waterstate.waterwidth;
8755         r_refdef.view.height = r_waterstate.waterheight;
8756         r_refdef.view.useclipplane = true;
8757         myview = r_refdef.view;
8758         r_waterstate.renderingscene = true;
8759         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8760         {
8761                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8762                 {
8763                         r_refdef.view = myview;
8764                         if(r_water_scissormode.integer)
8765                         {
8766                                 R_SetupView(true);
8767                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8768                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8769                         }
8770
8771                         // render reflected scene and copy into texture
8772                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8773                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8774                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8775                         r_refdef.view.clipplane = p->plane;
8776
8777                         // reverse the cullface settings for this render
8778                         r_refdef.view.cullface_front = GL_FRONT;
8779                         r_refdef.view.cullface_back = GL_BACK;
8780                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8781                         {
8782                                 r_refdef.view.usecustompvs = true;
8783                                 if (p->pvsvalid)
8784                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8785                                 else
8786                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8787                         }
8788
8789                         R_ResetViewRendering3D();
8790                         R_ClearScreen(r_refdef.fogenabled);
8791                         if(r_water_scissormode.integer & 2)
8792                                 R_View_UpdateWithScissor(myscissor);
8793                         else
8794                                 R_View_Update();
8795                         if(r_water_scissormode.integer & 1)
8796                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8797                         R_RenderScene();
8798
8799                         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);
8800                 }
8801
8802                 // render the normal view scene and copy into texture
8803                 // (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)
8804                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8805                 {
8806                         r_refdef.view = myview;
8807                         if(r_water_scissormode.integer)
8808                         {
8809                                 R_SetupView(true);
8810                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8811                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8812                         }
8813
8814                         r_waterstate.renderingrefraction = true;
8815
8816                         r_refdef.view.clipplane = p->plane;
8817                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8818                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8819
8820                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8821                         {
8822                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8823                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8824                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8825                                 R_RenderView_UpdateViewVectors();
8826                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8827                                 {
8828                                         r_refdef.view.usecustompvs = true;
8829                                         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);
8830                                 }
8831                         }
8832
8833                         PlaneClassify(&r_refdef.view.clipplane);
8834
8835                         R_ResetViewRendering3D();
8836                         R_ClearScreen(r_refdef.fogenabled);
8837                         if(r_water_scissormode.integer & 2)
8838                                 R_View_UpdateWithScissor(myscissor);
8839                         else
8840                                 R_View_Update();
8841                         if(r_water_scissormode.integer & 1)
8842                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8843                         R_RenderScene();
8844
8845                         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);
8846                         r_waterstate.renderingrefraction = false;
8847                 }
8848                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8849                 {
8850                         r_refdef.view = myview;
8851
8852                         r_refdef.view.clipplane = p->plane;
8853                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8854                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8855
8856                         r_refdef.view.width = r_waterstate.camerawidth;
8857                         r_refdef.view.height = r_waterstate.cameraheight;
8858                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8859                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8860
8861                         if(p->camera_entity)
8862                         {
8863                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8864                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8865                         }
8866
8867                         // note: all of the view is used for displaying... so
8868                         // there is no use in scissoring
8869
8870                         // reverse the cullface settings for this render
8871                         r_refdef.view.cullface_front = GL_FRONT;
8872                         r_refdef.view.cullface_back = GL_BACK;
8873                         // also reverse the view matrix
8874                         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
8875                         R_RenderView_UpdateViewVectors();
8876                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8877                         {
8878                                 r_refdef.view.usecustompvs = true;
8879                                 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);
8880                         }
8881                         
8882                         // camera needs no clipplane
8883                         r_refdef.view.useclipplane = false;
8884
8885                         PlaneClassify(&r_refdef.view.clipplane);
8886
8887                         R_ResetViewRendering3D();
8888                         R_ClearScreen(r_refdef.fogenabled);
8889                         R_View_Update();
8890                         R_RenderScene();
8891
8892                         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);
8893                         r_waterstate.renderingrefraction = false;
8894                 }
8895
8896         }
8897         r_waterstate.renderingscene = false;
8898         r_refdef.view = originalview;
8899         R_ResetViewRendering3D();
8900         R_ClearScreen(r_refdef.fogenabled);
8901         R_View_Update();
8902         return;
8903 error:
8904         r_refdef.view = originalview;
8905         r_waterstate.renderingscene = false;
8906         Cvar_SetValueQuick(&r_water, 0);
8907         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8908         return;
8909 }
8910
8911 void R_Bloom_StartFrame(void)
8912 {
8913         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8914
8915         switch(vid.renderpath)
8916         {
8917         case RENDERPATH_GL20:
8918         case RENDERPATH_CGGL:
8919         case RENDERPATH_D3D9:
8920         case RENDERPATH_D3D10:
8921         case RENDERPATH_D3D11:
8922                 break;
8923         case RENDERPATH_GL13:
8924         case RENDERPATH_GL11:
8925                 return;
8926         }
8927
8928         // set bloomwidth and bloomheight to the bloom resolution that will be
8929         // used (often less than the screen resolution for faster rendering)
8930         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8931         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8932         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8933         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8934         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8935
8936         // calculate desired texture sizes
8937         if (vid.support.arb_texture_non_power_of_two)
8938         {
8939                 screentexturewidth = r_refdef.view.width;
8940                 screentextureheight = r_refdef.view.height;
8941                 bloomtexturewidth = r_bloomstate.bloomwidth;
8942                 bloomtextureheight = r_bloomstate.bloomheight;
8943         }
8944         else
8945         {
8946                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8947                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8948                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8949                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8950         }
8951
8952         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))
8953         {
8954                 Cvar_SetValueQuick(&r_hdr, 0);
8955                 Cvar_SetValueQuick(&r_bloom, 0);
8956                 Cvar_SetValueQuick(&r_motionblur, 0);
8957                 Cvar_SetValueQuick(&r_damageblur, 0);
8958         }
8959
8960         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)))
8961                 screentexturewidth = screentextureheight = 0;
8962         if (!r_hdr.integer && !r_bloom.integer)
8963                 bloomtexturewidth = bloomtextureheight = 0;
8964
8965         // allocate textures as needed
8966         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8967         {
8968                 if (r_bloomstate.texture_screen)
8969                         R_FreeTexture(r_bloomstate.texture_screen);
8970                 r_bloomstate.texture_screen = NULL;
8971                 r_bloomstate.screentexturewidth = screentexturewidth;
8972                 r_bloomstate.screentextureheight = screentextureheight;
8973                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8974                         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);
8975         }
8976         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8977         {
8978                 if (r_bloomstate.texture_bloom)
8979                         R_FreeTexture(r_bloomstate.texture_bloom);
8980                 r_bloomstate.texture_bloom = NULL;
8981                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8982                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8983                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8984                         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);
8985         }
8986
8987         // when doing a reduced render (HDR) we want to use a smaller area
8988         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8989         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8990         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8991         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8992         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8993
8994         // set up a texcoord array for the full resolution screen image
8995         // (we have to keep this around to copy back during final render)
8996         r_bloomstate.screentexcoord2f[0] = 0;
8997         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8998         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8999         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
9000         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
9001         r_bloomstate.screentexcoord2f[5] = 0;
9002         r_bloomstate.screentexcoord2f[6] = 0;
9003         r_bloomstate.screentexcoord2f[7] = 0;
9004
9005         // set up a texcoord array for the reduced resolution bloom image
9006         // (which will be additive blended over the screen image)
9007         r_bloomstate.bloomtexcoord2f[0] = 0;
9008         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9009         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9010         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9011         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9012         r_bloomstate.bloomtexcoord2f[5] = 0;
9013         r_bloomstate.bloomtexcoord2f[6] = 0;
9014         r_bloomstate.bloomtexcoord2f[7] = 0;
9015
9016         switch(vid.renderpath)
9017         {
9018         case RENDERPATH_GL11:
9019         case RENDERPATH_GL13:
9020         case RENDERPATH_GL20:
9021         case RENDERPATH_CGGL:
9022                 break;
9023         case RENDERPATH_D3D9:
9024         case RENDERPATH_D3D10:
9025         case RENDERPATH_D3D11:
9026                 {
9027                         int i;
9028                         for (i = 0;i < 4;i++)
9029                         {
9030                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
9031                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
9032                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
9033                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
9034                         }
9035                 }
9036                 break;
9037         }
9038
9039         if (r_hdr.integer || r_bloom.integer)
9040         {
9041                 r_bloomstate.enabled = true;
9042                 r_bloomstate.hdr = r_hdr.integer != 0;
9043         }
9044
9045         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);
9046 }
9047
9048 void R_Bloom_CopyBloomTexture(float colorscale)
9049 {
9050         r_refdef.stats.bloom++;
9051
9052         // scale down screen texture to the bloom texture size
9053         CHECKGLERROR
9054         R_SetViewport(&r_bloomstate.viewport);
9055         GL_BlendFunc(GL_ONE, GL_ZERO);
9056         GL_Color(colorscale, colorscale, colorscale, 1);
9057         // 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...
9058         switch(vid.renderpath)
9059         {
9060         case RENDERPATH_GL11:
9061         case RENDERPATH_GL13:
9062         case RENDERPATH_GL20:
9063         case RENDERPATH_CGGL:
9064                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9065                 break;
9066         case RENDERPATH_D3D9:
9067         case RENDERPATH_D3D10:
9068         case RENDERPATH_D3D11:
9069                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9070                 break;
9071         }
9072         // TODO: do boxfilter scale-down in shader?
9073         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9074         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9075         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9076
9077         // we now have a bloom image in the framebuffer
9078         // copy it into the bloom image texture for later processing
9079         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);
9080         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9081 }
9082
9083 void R_Bloom_CopyHDRTexture(void)
9084 {
9085         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);
9086         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9087 }
9088
9089 void R_Bloom_MakeTexture(void)
9090 {
9091         int x, range, dir;
9092         float xoffset, yoffset, r, brighten;
9093
9094         r_refdef.stats.bloom++;
9095
9096         R_ResetViewRendering2D();
9097
9098         // we have a bloom image in the framebuffer
9099         CHECKGLERROR
9100         R_SetViewport(&r_bloomstate.viewport);
9101
9102         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9103         {
9104                 x *= 2;
9105                 r = bound(0, r_bloom_colorexponent.value / x, 1);
9106                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9107                 GL_Color(r,r,r,1);
9108                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9109                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9110                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9111                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9112
9113                 // copy the vertically blurred bloom view to a texture
9114                 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);
9115                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9116         }
9117
9118         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9119         brighten = r_bloom_brighten.value;
9120         if (r_hdr.integer)
9121                 brighten *= r_hdr_range.value;
9122         brighten = sqrt(brighten);
9123         if(range >= 1)
9124                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9125         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9126
9127         for (dir = 0;dir < 2;dir++)
9128         {
9129                 // blend on at multiple vertical offsets to achieve a vertical blur
9130                 // TODO: do offset blends using GLSL
9131                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9132                 GL_BlendFunc(GL_ONE, GL_ZERO);
9133                 for (x = -range;x <= range;x++)
9134                 {
9135                         if (!dir){xoffset = 0;yoffset = x;}
9136                         else {xoffset = x;yoffset = 0;}
9137                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
9138                         yoffset /= (float)r_bloomstate.bloomtextureheight;
9139                         // compute a texcoord array with the specified x and y offset
9140                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9141                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9142                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9143                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9144                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9145                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9146                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9147                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9148                         // this r value looks like a 'dot' particle, fading sharply to
9149                         // black at the edges
9150                         // (probably not realistic but looks good enough)
9151                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9152                         //r = brighten/(range*2+1);
9153                         r = brighten / (range * 2 + 1);
9154                         if(range >= 1)
9155                                 r *= (1 - x*x/(float)(range*range));
9156                         GL_Color(r, r, r, 1);
9157                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9158                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9159                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9160                         GL_BlendFunc(GL_ONE, GL_ONE);
9161                 }
9162
9163                 // copy the vertically blurred bloom view to a texture
9164                 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);
9165                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9166         }
9167 }
9168
9169 void R_HDR_RenderBloomTexture(void)
9170 {
9171         int oldwidth, oldheight;
9172         float oldcolorscale;
9173         int oldwaterstate;
9174
9175         oldwaterstate = r_waterstate.enabled;
9176         oldcolorscale = r_refdef.view.colorscale;
9177         oldwidth = r_refdef.view.width;
9178         oldheight = r_refdef.view.height;
9179         r_refdef.view.width = r_bloomstate.bloomwidth;
9180         r_refdef.view.height = r_bloomstate.bloomheight;
9181
9182         if(r_hdr.integer < 2)
9183                 r_waterstate.enabled = false;
9184
9185         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
9186         // TODO: add exposure compensation features
9187         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9188
9189         r_refdef.view.showdebug = false;
9190         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9191
9192         R_ResetViewRendering3D();
9193
9194         R_ClearScreen(r_refdef.fogenabled);
9195         if (r_timereport_active)
9196                 R_TimeReport("HDRclear");
9197
9198         R_View_Update();
9199         if (r_timereport_active)
9200                 R_TimeReport("visibility");
9201
9202         // only do secondary renders with HDR if r_hdr is 2 or higher
9203         r_waterstate.numwaterplanes = 0;
9204         if (r_waterstate.enabled)
9205                 R_RenderWaterPlanes();
9206
9207         r_refdef.view.showdebug = true;
9208         R_RenderScene();
9209         r_waterstate.numwaterplanes = 0;
9210
9211         R_ResetViewRendering2D();
9212
9213         R_Bloom_CopyHDRTexture();
9214         R_Bloom_MakeTexture();
9215
9216         // restore the view settings
9217         r_waterstate.enabled = oldwaterstate;
9218         r_refdef.view.width = oldwidth;
9219         r_refdef.view.height = oldheight;
9220         r_refdef.view.colorscale = oldcolorscale;
9221
9222         R_ResetViewRendering3D();
9223
9224         R_ClearScreen(r_refdef.fogenabled);
9225         if (r_timereport_active)
9226                 R_TimeReport("viewclear");
9227 }
9228
9229 static void R_BlendView(void)
9230 {
9231         unsigned int permutation;
9232         float uservecs[4][4];
9233
9234         switch (vid.renderpath)
9235         {
9236         case RENDERPATH_GL20:
9237         case RENDERPATH_CGGL:
9238         case RENDERPATH_D3D9:
9239         case RENDERPATH_D3D10:
9240         case RENDERPATH_D3D11:
9241                 permutation =
9242                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9243                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9244                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9245                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9246                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9247
9248                 if (r_bloomstate.texture_screen)
9249                 {
9250                         // make sure the buffer is available
9251                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9252
9253                         R_ResetViewRendering2D();
9254
9255                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9256                         {
9257                                 // declare variables
9258                                 float speed;
9259                                 static float avgspeed;
9260
9261                                 speed = VectorLength(cl.movement_velocity);
9262
9263                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9264                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9265
9266                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9267                                 speed = bound(0, speed, 1);
9268                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9269
9270                                 // calculate values into a standard alpha
9271                                 cl.motionbluralpha = 1 - exp(-
9272                                                 (
9273                                                  (r_motionblur.value * speed / 80)
9274                                                  +
9275                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9276                                                 )
9277                                                 /
9278                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
9279                                            );
9280
9281                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9282                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9283                                 // apply the blur
9284                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9285                                 {
9286                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9287                                         GL_Color(1, 1, 1, cl.motionbluralpha);
9288                                         switch(vid.renderpath)
9289                                         {
9290                                         case RENDERPATH_GL11:
9291                                         case RENDERPATH_GL13:
9292                                         case RENDERPATH_GL20:
9293                                         case RENDERPATH_CGGL:
9294                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9295                                                 break;
9296                                         case RENDERPATH_D3D9:
9297                                         case RENDERPATH_D3D10:
9298                                         case RENDERPATH_D3D11:
9299                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9300                                                 break;
9301                                         }
9302                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9303                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9304                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9305                                 }
9306                         }
9307
9308                         // copy view into the screen texture
9309                         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);
9310                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9311                 }
9312                 else if (!r_bloomstate.texture_bloom)
9313                 {
9314                         // we may still have to do view tint...
9315                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9316                         {
9317                                 // apply a color tint to the whole view
9318                                 R_ResetViewRendering2D();
9319                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9320                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9321                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9322                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9323                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9324                         }
9325                         break; // no screen processing, no bloom, skip it
9326                 }
9327
9328                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9329                 {
9330                         // render simple bloom effect
9331                         // copy the screen and shrink it and darken it for the bloom process
9332                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9333                         // make the bloom texture
9334                         R_Bloom_MakeTexture();
9335                 }
9336
9337 #if _MSC_VER >= 1400
9338 #define sscanf sscanf_s
9339 #endif
9340                 memset(uservecs, 0, sizeof(uservecs));
9341                 if (r_glsl_postprocess_uservec1_enable.integer)
9342                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9343                 if (r_glsl_postprocess_uservec2_enable.integer)
9344                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9345                 if (r_glsl_postprocess_uservec3_enable.integer)
9346                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9347                 if (r_glsl_postprocess_uservec4_enable.integer)
9348                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9349
9350                 R_ResetViewRendering2D();
9351                 GL_Color(1, 1, 1, 1);
9352                 GL_BlendFunc(GL_ONE, GL_ZERO);
9353
9354                 switch(vid.renderpath)
9355                 {
9356                 case RENDERPATH_GL20:
9357                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9358                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9359                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9360                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9361                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9362                         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]);
9363                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9364                         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]);
9365                         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]);
9366                         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]);
9367                         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]);
9368                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9369                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9370                         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);
9371                         break;
9372                 case RENDERPATH_CGGL:
9373 #ifdef SUPPORTCG
9374                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9375                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9376                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9377                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9378                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9379                         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
9380                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9381                         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
9382                         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
9383                         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
9384                         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
9385                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9386                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9387                         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);
9388 #endif
9389                         break;
9390                 case RENDERPATH_D3D9:
9391 #ifdef SUPPORTD3D
9392                         // 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...
9393                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9394                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9395                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9396                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9397                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9398                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9399                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9400                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9401                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9402                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9403                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9404                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9405                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9406                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9407 #endif
9408                         break;
9409                 case RENDERPATH_D3D10:
9410                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9411                         break;
9412                 case RENDERPATH_D3D11:
9413                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9414                         break;
9415                 default:
9416                         break;
9417                 }
9418                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9419                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9420                 break;
9421         case RENDERPATH_GL13:
9422         case RENDERPATH_GL11:
9423                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9424                 {
9425                         // apply a color tint to the whole view
9426                         R_ResetViewRendering2D();
9427                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9428                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9429                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9430                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9431                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9432                 }
9433                 break;
9434         }
9435 }
9436
9437 matrix4x4_t r_waterscrollmatrix;
9438
9439 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9440 {
9441         if (r_refdef.fog_density)
9442         {
9443                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9444                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9445                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9446
9447                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9448                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9449                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9450                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9451
9452                 {
9453                         vec3_t fogvec;
9454                         VectorCopy(r_refdef.fogcolor, fogvec);
9455                         //   color.rgb *= ContrastBoost * SceneBrightness;
9456                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9457                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9458                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9459                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9460                 }
9461         }
9462 }
9463
9464 void R_UpdateVariables(void)
9465 {
9466         R_Textures_Frame();
9467
9468         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9469
9470         r_refdef.farclip = r_farclip_base.value;
9471         if (r_refdef.scene.worldmodel)
9472                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9473         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9474
9475         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9476                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9477         r_refdef.polygonfactor = 0;
9478         r_refdef.polygonoffset = 0;
9479         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9480         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9481
9482         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9483         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9484         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
9485         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9486         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9487         if (FAKELIGHT_ENABLED)
9488         {
9489                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9490         }
9491         if (r_showsurfaces.integer)
9492         {
9493                 r_refdef.scene.rtworld = false;
9494                 r_refdef.scene.rtworldshadows = false;
9495                 r_refdef.scene.rtdlight = false;
9496                 r_refdef.scene.rtdlightshadows = false;
9497                 r_refdef.lightmapintensity = 0;
9498         }
9499
9500         if (gamemode == GAME_NEHAHRA)
9501         {
9502                 if (gl_fogenable.integer)
9503                 {
9504                         r_refdef.oldgl_fogenable = true;
9505                         r_refdef.fog_density = gl_fogdensity.value;
9506                         r_refdef.fog_red = gl_fogred.value;
9507                         r_refdef.fog_green = gl_foggreen.value;
9508                         r_refdef.fog_blue = gl_fogblue.value;
9509                         r_refdef.fog_alpha = 1;
9510                         r_refdef.fog_start = 0;
9511                         r_refdef.fog_end = gl_skyclip.value;
9512                         r_refdef.fog_height = 1<<30;
9513                         r_refdef.fog_fadedepth = 128;
9514                 }
9515                 else if (r_refdef.oldgl_fogenable)
9516                 {
9517                         r_refdef.oldgl_fogenable = false;
9518                         r_refdef.fog_density = 0;
9519                         r_refdef.fog_red = 0;
9520                         r_refdef.fog_green = 0;
9521                         r_refdef.fog_blue = 0;
9522                         r_refdef.fog_alpha = 0;
9523                         r_refdef.fog_start = 0;
9524                         r_refdef.fog_end = 0;
9525                         r_refdef.fog_height = 1<<30;
9526                         r_refdef.fog_fadedepth = 128;
9527                 }
9528         }
9529
9530         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9531         r_refdef.fog_start = max(0, r_refdef.fog_start);
9532         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9533
9534         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9535
9536         if (r_refdef.fog_density && r_drawfog.integer)
9537         {
9538                 r_refdef.fogenabled = true;
9539                 // this is the point where the fog reaches 0.9986 alpha, which we
9540                 // consider a good enough cutoff point for the texture
9541                 // (0.9986 * 256 == 255.6)
9542                 if (r_fog_exp2.integer)
9543                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9544                 else
9545                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9546                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9547                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9548                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9549                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9550                         R_BuildFogHeightTexture();
9551                 // fog color was already set
9552                 // update the fog texture
9553                 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)
9554                         R_BuildFogTexture();
9555                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9556                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9557         }
9558         else
9559                 r_refdef.fogenabled = false;
9560
9561         switch(vid.renderpath)
9562         {
9563         case RENDERPATH_GL20:
9564         case RENDERPATH_CGGL:
9565         case RENDERPATH_D3D9:
9566         case RENDERPATH_D3D10:
9567         case RENDERPATH_D3D11:
9568                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9569                 {
9570                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9571                         {
9572                                 // build GLSL gamma texture
9573 #define RAMPWIDTH 256
9574                                 unsigned short ramp[RAMPWIDTH * 3];
9575                                 unsigned char rampbgr[RAMPWIDTH][4];
9576                                 int i;
9577
9578                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9579
9580                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9581                                 for(i = 0; i < RAMPWIDTH; ++i)
9582                                 {
9583                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9584                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9585                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9586                                         rampbgr[i][3] = 0;
9587                                 }
9588                                 if (r_texture_gammaramps)
9589                                 {
9590                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9591                                 }
9592                                 else
9593                                 {
9594                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9595                                 }
9596                         }
9597                 }
9598                 else
9599                 {
9600                         // remove GLSL gamma texture
9601                 }
9602                 break;
9603         case RENDERPATH_GL13:
9604         case RENDERPATH_GL11:
9605                 break;
9606         }
9607 }
9608
9609 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9610 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9611 /*
9612 ================
9613 R_SelectScene
9614 ================
9615 */
9616 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9617         if( scenetype != r_currentscenetype ) {
9618                 // store the old scenetype
9619                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9620                 r_currentscenetype = scenetype;
9621                 // move in the new scene
9622                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9623         }
9624 }
9625
9626 /*
9627 ================
9628 R_GetScenePointer
9629 ================
9630 */
9631 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9632 {
9633         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9634         if( scenetype == r_currentscenetype ) {
9635                 return &r_refdef.scene;
9636         } else {
9637                 return &r_scenes_store[ scenetype ];
9638         }
9639 }
9640
9641 /*
9642 ================
9643 R_RenderView
9644 ================
9645 */
9646 void R_RenderView(void)
9647 {
9648         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9649         if (r_timereport_active)
9650                 R_TimeReport("start");
9651         r_textureframe++; // used only by R_GetCurrentTexture
9652         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9653
9654         if(R_CompileShader_CheckStaticParms())
9655                 R_GLSL_Restart_f();
9656
9657         if (!r_drawentities.integer)
9658                 r_refdef.scene.numentities = 0;
9659
9660         R_AnimCache_ClearCache();
9661         R_FrameData_NewFrame();
9662
9663         /* adjust for stereo display */
9664         if(R_Stereo_Active())
9665         {
9666                 Matrix4x4_CreateFromQuakeEntity(&offsetmatrix, 0, r_stereo_separation.value * (0.5f - r_stereo_side), 0, 0, r_stereo_angle.value * (0.5f - r_stereo_side), 0, 1);
9667                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9668         }
9669
9670         if (r_refdef.view.isoverlay)
9671         {
9672                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9673                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9674                 R_TimeReport("depthclear");
9675
9676                 r_refdef.view.showdebug = false;
9677
9678                 r_waterstate.enabled = false;
9679                 r_waterstate.numwaterplanes = 0;
9680
9681                 R_RenderScene();
9682
9683                 r_refdef.view.matrix = originalmatrix;
9684
9685                 CHECKGLERROR
9686                 return;
9687         }
9688
9689         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9690         {
9691                 r_refdef.view.matrix = originalmatrix;
9692                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9693         }
9694
9695         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9696
9697         R_RenderView_UpdateViewVectors();
9698
9699         R_Shadow_UpdateWorldLightSelection();
9700
9701         R_Bloom_StartFrame();
9702         R_Water_StartFrame();
9703
9704         CHECKGLERROR
9705         if (r_timereport_active)
9706                 R_TimeReport("viewsetup");
9707
9708         R_ResetViewRendering3D();
9709
9710         if (r_refdef.view.clear || r_refdef.fogenabled)
9711         {
9712                 R_ClearScreen(r_refdef.fogenabled);
9713                 if (r_timereport_active)
9714                         R_TimeReport("viewclear");
9715         }
9716         r_refdef.view.clear = true;
9717
9718         // this produces a bloom texture to be used in R_BlendView() later
9719         if (r_hdr.integer && r_bloomstate.bloomwidth)
9720         {
9721                 R_HDR_RenderBloomTexture();
9722                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9723                 r_textureframe++; // used only by R_GetCurrentTexture
9724         }
9725
9726         r_refdef.view.showdebug = true;
9727
9728         R_View_Update();
9729         if (r_timereport_active)
9730                 R_TimeReport("visibility");
9731
9732         r_waterstate.numwaterplanes = 0;
9733         if (r_waterstate.enabled)
9734                 R_RenderWaterPlanes();
9735
9736         R_RenderScene();
9737         r_waterstate.numwaterplanes = 0;
9738
9739         R_BlendView();
9740         if (r_timereport_active)
9741                 R_TimeReport("blendview");
9742
9743         GL_Scissor(0, 0, vid.width, vid.height);
9744         GL_ScissorTest(false);
9745
9746         r_refdef.view.matrix = originalmatrix;
9747
9748         CHECKGLERROR
9749 }
9750
9751 void R_RenderWaterPlanes(void)
9752 {
9753         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9754         {
9755                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9756                 if (r_timereport_active)
9757                         R_TimeReport("waterworld");
9758         }
9759
9760         // don't let sound skip if going slow
9761         if (r_refdef.scene.extraupdate)
9762                 S_ExtraUpdate ();
9763
9764         R_DrawModelsAddWaterPlanes();
9765         if (r_timereport_active)
9766                 R_TimeReport("watermodels");
9767
9768         if (r_waterstate.numwaterplanes)
9769         {
9770                 R_Water_ProcessPlanes();
9771                 if (r_timereport_active)
9772                         R_TimeReport("waterscenes");
9773         }
9774 }
9775
9776 extern void R_DrawLightningBeams (void);
9777 extern void VM_CL_AddPolygonsToMeshQueue (void);
9778 extern void R_DrawPortals (void);
9779 extern cvar_t cl_locs_show;
9780 static void R_DrawLocs(void);
9781 static void R_DrawEntityBBoxes(void);
9782 static void R_DrawModelDecals(void);
9783 extern void R_DrawModelShadows(void);
9784 extern void R_DrawModelShadowMaps(void);
9785 extern cvar_t cl_decals_newsystem;
9786 extern qboolean r_shadow_usingdeferredprepass;
9787 void R_RenderScene(void)
9788 {
9789         qboolean shadowmapping = false;
9790
9791         if (r_timereport_active)
9792                 R_TimeReport("beginscene");
9793
9794         r_refdef.stats.renders++;
9795
9796         R_UpdateFogColor();
9797
9798         // don't let sound skip if going slow
9799         if (r_refdef.scene.extraupdate)
9800                 S_ExtraUpdate ();
9801
9802         R_MeshQueue_BeginScene();
9803
9804         R_SkyStartFrame();
9805
9806         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);
9807
9808         if (r_timereport_active)
9809                 R_TimeReport("skystartframe");
9810
9811         if (cl.csqc_vidvars.drawworld)
9812         {
9813                 // don't let sound skip if going slow
9814                 if (r_refdef.scene.extraupdate)
9815                         S_ExtraUpdate ();
9816
9817                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9818                 {
9819                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9820                         if (r_timereport_active)
9821                                 R_TimeReport("worldsky");
9822                 }
9823
9824                 if (R_DrawBrushModelsSky() && r_timereport_active)
9825                         R_TimeReport("bmodelsky");
9826
9827                 if (skyrendermasked && skyrenderlater)
9828                 {
9829                         // we have to force off the water clipping plane while rendering sky
9830                         R_SetupView(false);
9831                         R_Sky();
9832                         R_SetupView(true);
9833                         if (r_timereport_active)
9834                                 R_TimeReport("sky");
9835                 }
9836         }
9837
9838         R_AnimCache_CacheVisibleEntities();
9839         if (r_timereport_active)
9840                 R_TimeReport("animation");
9841
9842         R_Shadow_PrepareLights();
9843         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9844                 R_Shadow_PrepareModelShadows();
9845         if (r_timereport_active)
9846                 R_TimeReport("preparelights");
9847
9848         if (R_Shadow_ShadowMappingEnabled())
9849                 shadowmapping = true;
9850
9851         if (r_shadow_usingdeferredprepass)
9852                 R_Shadow_DrawPrepass();
9853
9854         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9855         {
9856                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9857                 if (r_timereport_active)
9858                         R_TimeReport("worlddepth");
9859         }
9860         if (r_depthfirst.integer >= 2)
9861         {
9862                 R_DrawModelsDepth();
9863                 if (r_timereport_active)
9864                         R_TimeReport("modeldepth");
9865         }
9866
9867         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9868         {
9869                 R_DrawModelShadowMaps();
9870                 R_ResetViewRendering3D();
9871                 // don't let sound skip if going slow
9872                 if (r_refdef.scene.extraupdate)
9873                         S_ExtraUpdate ();
9874         }
9875
9876         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9877         {
9878                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9879                 if (r_timereport_active)
9880                         R_TimeReport("world");
9881         }
9882
9883         // don't let sound skip if going slow
9884         if (r_refdef.scene.extraupdate)
9885                 S_ExtraUpdate ();
9886
9887         R_DrawModels();
9888         if (r_timereport_active)
9889                 R_TimeReport("models");
9890
9891         // don't let sound skip if going slow
9892         if (r_refdef.scene.extraupdate)
9893                 S_ExtraUpdate ();
9894
9895         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9896         {
9897                 R_DrawModelShadows();
9898                 R_ResetViewRendering3D();
9899                 // don't let sound skip if going slow
9900                 if (r_refdef.scene.extraupdate)
9901                         S_ExtraUpdate ();
9902         }
9903
9904         if (!r_shadow_usingdeferredprepass)
9905         {
9906                 R_Shadow_DrawLights();
9907                 if (r_timereport_active)
9908                         R_TimeReport("rtlights");
9909         }
9910
9911         // don't let sound skip if going slow
9912         if (r_refdef.scene.extraupdate)
9913                 S_ExtraUpdate ();
9914
9915         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9916         {
9917                 R_DrawModelShadows();
9918                 R_ResetViewRendering3D();
9919                 // don't let sound skip if going slow
9920                 if (r_refdef.scene.extraupdate)
9921                         S_ExtraUpdate ();
9922         }
9923
9924         if (cl.csqc_vidvars.drawworld)
9925         {
9926                 if (cl_decals_newsystem.integer)
9927                 {
9928                         R_DrawModelDecals();
9929                         if (r_timereport_active)
9930                                 R_TimeReport("modeldecals");
9931                 }
9932                 else
9933                 {
9934                         R_DrawDecals();
9935                         if (r_timereport_active)
9936                                 R_TimeReport("decals");
9937                 }
9938
9939                 R_DrawParticles();
9940                 if (r_timereport_active)
9941                         R_TimeReport("particles");
9942
9943                 R_DrawExplosions();
9944                 if (r_timereport_active)
9945                         R_TimeReport("explosions");
9946
9947                 R_DrawLightningBeams();
9948                 if (r_timereport_active)
9949                         R_TimeReport("lightning");
9950         }
9951
9952         VM_CL_AddPolygonsToMeshQueue();
9953
9954         if (r_refdef.view.showdebug)
9955         {
9956                 if (cl_locs_show.integer)
9957                 {
9958                         R_DrawLocs();
9959                         if (r_timereport_active)
9960                                 R_TimeReport("showlocs");
9961                 }
9962
9963                 if (r_drawportals.integer)
9964                 {
9965                         R_DrawPortals();
9966                         if (r_timereport_active)
9967                                 R_TimeReport("portals");
9968                 }
9969
9970                 if (r_showbboxes.value > 0)
9971                 {
9972                         R_DrawEntityBBoxes();
9973                         if (r_timereport_active)
9974                                 R_TimeReport("bboxes");
9975                 }
9976         }
9977
9978         R_MeshQueue_RenderTransparent();
9979         if (r_timereport_active)
9980                 R_TimeReport("drawtrans");
9981
9982         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))
9983         {
9984                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9985                 if (r_timereport_active)
9986                         R_TimeReport("worlddebug");
9987                 R_DrawModelsDebug();
9988                 if (r_timereport_active)
9989                         R_TimeReport("modeldebug");
9990         }
9991
9992         if (cl.csqc_vidvars.drawworld)
9993         {
9994                 R_Shadow_DrawCoronas();
9995                 if (r_timereport_active)
9996                         R_TimeReport("coronas");
9997         }
9998
9999 #if 0
10000         {
10001                 GL_DepthTest(false);
10002                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10003                 GL_Color(1, 1, 1, 1);
10004                 qglBegin(GL_POLYGON);
10005                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
10006                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
10007                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
10008                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
10009                 qglEnd();
10010                 qglBegin(GL_POLYGON);
10011                 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]);
10012                 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]);
10013                 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]);
10014                 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]);
10015                 qglEnd();
10016                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10017         }
10018 #endif
10019
10020         // don't let sound skip if going slow
10021         if (r_refdef.scene.extraupdate)
10022                 S_ExtraUpdate ();
10023
10024         R_ResetViewRendering2D();
10025 }
10026
10027 static const unsigned short bboxelements[36] =
10028 {
10029         5, 1, 3, 5, 3, 7,
10030         6, 2, 0, 6, 0, 4,
10031         7, 3, 2, 7, 2, 6,
10032         4, 0, 1, 4, 1, 5,
10033         4, 5, 7, 4, 7, 6,
10034         1, 0, 2, 1, 2, 3,
10035 };
10036
10037 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
10038 {
10039         int i;
10040         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
10041
10042         RSurf_ActiveWorldEntity();
10043
10044         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10045         GL_DepthMask(false);
10046         GL_DepthRange(0, 1);
10047         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10048 //      R_Mesh_ResetTextureState();
10049
10050         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
10051         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
10052         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
10053         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
10054         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
10055         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
10056         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
10057         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
10058         R_FillColors(color4f, 8, cr, cg, cb, ca);
10059         if (r_refdef.fogenabled)
10060         {
10061                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
10062                 {
10063                         f1 = RSurf_FogVertex(v);
10064                         f2 = 1 - f1;
10065                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
10066                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
10067                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
10068                 }
10069         }
10070         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
10071         R_Mesh_ResetTextureState();
10072         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10073         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
10074 }
10075
10076 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10077 {
10078         int i;
10079         float color[4];
10080         prvm_edict_t *edict;
10081         prvm_prog_t *prog_save = prog;
10082
10083         // this function draws bounding boxes of server entities
10084         if (!sv.active)
10085                 return;
10086
10087         GL_CullFace(GL_NONE);
10088         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10089
10090         prog = 0;
10091         SV_VM_Begin();
10092         for (i = 0;i < numsurfaces;i++)
10093         {
10094                 edict = PRVM_EDICT_NUM(surfacelist[i]);
10095                 switch ((int)edict->fields.server->solid)
10096                 {
10097                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
10098                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
10099                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
10100                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
10101                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
10102                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
10103                 }
10104                 color[3] *= r_showbboxes.value;
10105                 color[3] = bound(0, color[3], 1);
10106                 GL_DepthTest(!r_showdisabledepthtest.integer);
10107                 GL_CullFace(r_refdef.view.cullface_front);
10108                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10109         }
10110         SV_VM_End();
10111         prog = prog_save;
10112 }
10113
10114 static void R_DrawEntityBBoxes(void)
10115 {
10116         int i;
10117         prvm_edict_t *edict;
10118         vec3_t center;
10119         prvm_prog_t *prog_save = prog;
10120
10121         // this function draws bounding boxes of server entities
10122         if (!sv.active)
10123                 return;
10124
10125         prog = 0;
10126         SV_VM_Begin();
10127         for (i = 0;i < prog->num_edicts;i++)
10128         {
10129                 edict = PRVM_EDICT_NUM(i);
10130                 if (edict->priv.server->free)
10131                         continue;
10132                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10133                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10134                         continue;
10135                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10136                         continue;
10137                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10138                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10139         }
10140         SV_VM_End();
10141         prog = prog_save;
10142 }
10143
10144 static const int nomodelelement3i[24] =
10145 {
10146         5, 2, 0,
10147         5, 1, 2,
10148         5, 0, 3,
10149         5, 3, 1,
10150         0, 2, 4,
10151         2, 1, 4,
10152         3, 0, 4,
10153         1, 3, 4
10154 };
10155
10156 static const unsigned short nomodelelement3s[24] =
10157 {
10158         5, 2, 0,
10159         5, 1, 2,
10160         5, 0, 3,
10161         5, 3, 1,
10162         0, 2, 4,
10163         2, 1, 4,
10164         3, 0, 4,
10165         1, 3, 4
10166 };
10167
10168 static const float nomodelvertex3f[6*3] =
10169 {
10170         -16,   0,   0,
10171          16,   0,   0,
10172           0, -16,   0,
10173           0,  16,   0,
10174           0,   0, -16,
10175           0,   0,  16
10176 };
10177
10178 static const float nomodelcolor4f[6*4] =
10179 {
10180         0.0f, 0.0f, 0.5f, 1.0f,
10181         0.0f, 0.0f, 0.5f, 1.0f,
10182         0.0f, 0.5f, 0.0f, 1.0f,
10183         0.0f, 0.5f, 0.0f, 1.0f,
10184         0.5f, 0.0f, 0.0f, 1.0f,
10185         0.5f, 0.0f, 0.0f, 1.0f
10186 };
10187
10188 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10189 {
10190         int i;
10191         float f1, f2, *c;
10192         float color4f[6*4];
10193
10194         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);
10195
10196         // this is only called once per entity so numsurfaces is always 1, and
10197         // surfacelist is always {0}, so this code does not handle batches
10198
10199         if (rsurface.ent_flags & RENDER_ADDITIVE)
10200         {
10201                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10202                 GL_DepthMask(false);
10203         }
10204         else if (rsurface.colormod[3] < 1)
10205         {
10206                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10207                 GL_DepthMask(false);
10208         }
10209         else
10210         {
10211                 GL_BlendFunc(GL_ONE, GL_ZERO);
10212                 GL_DepthMask(true);
10213         }
10214         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10215         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10216         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10217         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10218         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10219         for (i = 0, c = color4f;i < 6;i++, c += 4)
10220         {
10221                 c[0] *= rsurface.colormod[0];
10222                 c[1] *= rsurface.colormod[1];
10223                 c[2] *= rsurface.colormod[2];
10224                 c[3] *= rsurface.colormod[3];
10225         }
10226         if (r_refdef.fogenabled)
10227         {
10228                 for (i = 0, c = color4f;i < 6;i++, c += 4)
10229                 {
10230                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10231                         f2 = 1 - f1;
10232                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10233                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10234                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10235                 }
10236         }
10237 //      R_Mesh_ResetTextureState();
10238         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10239         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10240         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10241 }
10242
10243 void R_DrawNoModel(entity_render_t *ent)
10244 {
10245         vec3_t org;
10246         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10247         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10248                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10249         else
10250                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10251 }
10252
10253 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10254 {
10255         vec3_t right1, right2, diff, normal;
10256
10257         VectorSubtract (org2, org1, normal);
10258
10259         // calculate 'right' vector for start
10260         VectorSubtract (r_refdef.view.origin, org1, diff);
10261         CrossProduct (normal, diff, right1);
10262         VectorNormalize (right1);
10263
10264         // calculate 'right' vector for end
10265         VectorSubtract (r_refdef.view.origin, org2, diff);
10266         CrossProduct (normal, diff, right2);
10267         VectorNormalize (right2);
10268
10269         vert[ 0] = org1[0] + width * right1[0];
10270         vert[ 1] = org1[1] + width * right1[1];
10271         vert[ 2] = org1[2] + width * right1[2];
10272         vert[ 3] = org1[0] - width * right1[0];
10273         vert[ 4] = org1[1] - width * right1[1];
10274         vert[ 5] = org1[2] - width * right1[2];
10275         vert[ 6] = org2[0] - width * right2[0];
10276         vert[ 7] = org2[1] - width * right2[1];
10277         vert[ 8] = org2[2] - width * right2[2];
10278         vert[ 9] = org2[0] + width * right2[0];
10279         vert[10] = org2[1] + width * right2[1];
10280         vert[11] = org2[2] + width * right2[2];
10281 }
10282
10283 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)
10284 {
10285         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10286         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10287         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10288         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10289         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10290         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10291         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10292         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10293         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10294         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10295         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10296         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10297 }
10298
10299 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10300 {
10301         int i;
10302         float *vertex3f;
10303         float v[3];
10304         VectorSet(v, x, y, z);
10305         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10306                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10307                         break;
10308         if (i == mesh->numvertices)
10309         {
10310                 if (mesh->numvertices < mesh->maxvertices)
10311                 {
10312                         VectorCopy(v, vertex3f);
10313                         mesh->numvertices++;
10314                 }
10315                 return mesh->numvertices;
10316         }
10317         else
10318                 return i;
10319 }
10320
10321 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10322 {
10323         int i;
10324         int *e, element[3];
10325         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10326         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10327         e = mesh->element3i + mesh->numtriangles * 3;
10328         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10329         {
10330                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10331                 if (mesh->numtriangles < mesh->maxtriangles)
10332                 {
10333                         *e++ = element[0];
10334                         *e++ = element[1];
10335                         *e++ = element[2];
10336                         mesh->numtriangles++;
10337                 }
10338                 element[1] = element[2];
10339         }
10340 }
10341
10342 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10343 {
10344         int i;
10345         int *e, element[3];
10346         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10347         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10348         e = mesh->element3i + mesh->numtriangles * 3;
10349         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10350         {
10351                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10352                 if (mesh->numtriangles < mesh->maxtriangles)
10353                 {
10354                         *e++ = element[0];
10355                         *e++ = element[1];
10356                         *e++ = element[2];
10357                         mesh->numtriangles++;
10358                 }
10359                 element[1] = element[2];
10360         }
10361 }
10362
10363 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10364 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10365 {
10366         int planenum, planenum2;
10367         int w;
10368         int tempnumpoints;
10369         mplane_t *plane, *plane2;
10370         double maxdist;
10371         double temppoints[2][256*3];
10372         // figure out how large a bounding box we need to properly compute this brush
10373         maxdist = 0;
10374         for (w = 0;w < numplanes;w++)
10375                 maxdist = max(maxdist, fabs(planes[w].dist));
10376         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10377         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10378         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10379         {
10380                 w = 0;
10381                 tempnumpoints = 4;
10382                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10383                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10384                 {
10385                         if (planenum2 == planenum)
10386                                 continue;
10387                         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);
10388                         w = !w;
10389                 }
10390                 if (tempnumpoints < 3)
10391                         continue;
10392                 // generate elements forming a triangle fan for this polygon
10393                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10394         }
10395 }
10396
10397 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)
10398 {
10399         texturelayer_t *layer;
10400         layer = t->currentlayers + t->currentnumlayers++;
10401         layer->type = type;
10402         layer->depthmask = depthmask;
10403         layer->blendfunc1 = blendfunc1;
10404         layer->blendfunc2 = blendfunc2;
10405         layer->texture = texture;
10406         layer->texmatrix = *matrix;
10407         layer->color[0] = r;
10408         layer->color[1] = g;
10409         layer->color[2] = b;
10410         layer->color[3] = a;
10411 }
10412
10413 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10414 {
10415         if(parms[0] == 0 && parms[1] == 0)
10416                 return false;
10417         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10418                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10419                         return false;
10420         return true;
10421 }
10422
10423 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10424 {
10425         double index, f;
10426         index = parms[2] + r_refdef.scene.time * parms[3];
10427         index -= floor(index);
10428         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10429         {
10430         default:
10431         case Q3WAVEFUNC_NONE:
10432         case Q3WAVEFUNC_NOISE:
10433         case Q3WAVEFUNC_COUNT:
10434                 f = 0;
10435                 break;
10436         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10437         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10438         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10439         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10440         case Q3WAVEFUNC_TRIANGLE:
10441                 index *= 4;
10442                 f = index - floor(index);
10443                 if (index < 1)
10444                         f = f;
10445                 else if (index < 2)
10446                         f = 1 - f;
10447                 else if (index < 3)
10448                         f = -f;
10449                 else
10450                         f = -(1 - f);
10451                 break;
10452         }
10453         f = parms[0] + parms[1] * f;
10454         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10455                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10456         return (float) f;
10457 }
10458
10459 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10460 {
10461         int w, h, idx;
10462         float f;
10463         float tcmat[12];
10464         matrix4x4_t matrix, temp;
10465         switch(tcmod->tcmod)
10466         {
10467                 case Q3TCMOD_COUNT:
10468                 case Q3TCMOD_NONE:
10469                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10470                                 matrix = r_waterscrollmatrix;
10471                         else
10472                                 matrix = identitymatrix;
10473                         break;
10474                 case Q3TCMOD_ENTITYTRANSLATE:
10475                         // this is used in Q3 to allow the gamecode to control texcoord
10476                         // scrolling on the entity, which is not supported in darkplaces yet.
10477                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10478                         break;
10479                 case Q3TCMOD_ROTATE:
10480                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10481                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10482                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10483                         break;
10484                 case Q3TCMOD_SCALE:
10485                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10486                         break;
10487                 case Q3TCMOD_SCROLL:
10488                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10489                         break;
10490                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10491                         w = (int) tcmod->parms[0];
10492                         h = (int) tcmod->parms[1];
10493                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10494                         f = f - floor(f);
10495                         idx = (int) floor(f * w * h);
10496                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10497                         break;
10498                 case Q3TCMOD_STRETCH:
10499                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10500                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10501                         break;
10502                 case Q3TCMOD_TRANSFORM:
10503                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10504                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10505                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10506                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10507                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10508                         break;
10509                 case Q3TCMOD_TURBULENT:
10510                         // this is handled in the RSurf_PrepareVertices function
10511                         matrix = identitymatrix;
10512                         break;
10513         }
10514         temp = *texmatrix;
10515         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10516 }
10517
10518 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10519 {
10520         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10521         char name[MAX_QPATH];
10522         skinframe_t *skinframe;
10523         unsigned char pixels[296*194];
10524         strlcpy(cache->name, skinname, sizeof(cache->name));
10525         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10526         if (developer_loading.integer)
10527                 Con_Printf("loading %s\n", name);
10528         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10529         if (!skinframe || !skinframe->base)
10530         {
10531                 unsigned char *f;
10532                 fs_offset_t filesize;
10533                 skinframe = NULL;
10534                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10535                 if (f)
10536                 {
10537                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10538                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10539                         Mem_Free(f);
10540                 }
10541         }
10542         cache->skinframe = skinframe;
10543 }
10544
10545 texture_t *R_GetCurrentTexture(texture_t *t)
10546 {
10547         int i;
10548         const entity_render_t *ent = rsurface.entity;
10549         dp_model_t *model = ent->model;
10550         q3shaderinfo_layer_tcmod_t *tcmod;
10551
10552         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10553                 return t->currentframe;
10554         t->update_lastrenderframe = r_textureframe;
10555         t->update_lastrenderentity = (void *)ent;
10556
10557         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10558                 t->camera_entity = ent->entitynumber;
10559         else
10560                 t->camera_entity = 0;
10561
10562         // switch to an alternate material if this is a q1bsp animated material
10563         {
10564                 texture_t *texture = t;
10565                 int s = rsurface.ent_skinnum;
10566                 if ((unsigned int)s >= (unsigned int)model->numskins)
10567                         s = 0;
10568                 if (model->skinscenes)
10569                 {
10570                         if (model->skinscenes[s].framecount > 1)
10571                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10572                         else
10573                                 s = model->skinscenes[s].firstframe;
10574                 }
10575                 if (s > 0)
10576                         t = t + s * model->num_surfaces;
10577                 if (t->animated)
10578                 {
10579                         // use an alternate animation if the entity's frame is not 0,
10580                         // and only if the texture has an alternate animation
10581                         if (rsurface.ent_alttextures && t->anim_total[1])
10582                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10583                         else
10584                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10585                 }
10586                 texture->currentframe = t;
10587         }
10588
10589         // update currentskinframe to be a qw skin or animation frame
10590         if (rsurface.ent_qwskin >= 0)
10591         {
10592                 i = rsurface.ent_qwskin;
10593                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10594                 {
10595                         r_qwskincache_size = cl.maxclients;
10596                         if (r_qwskincache)
10597                                 Mem_Free(r_qwskincache);
10598                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10599                 }
10600                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10601                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10602                 t->currentskinframe = r_qwskincache[i].skinframe;
10603                 if (t->currentskinframe == NULL)
10604                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10605         }
10606         else if (t->numskinframes >= 2)
10607                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10608         if (t->backgroundnumskinframes >= 2)
10609                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10610
10611         t->currentmaterialflags = t->basematerialflags;
10612         t->currentalpha = rsurface.colormod[3];
10613         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10614                 t->currentalpha *= r_wateralpha.value;
10615         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10616                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10617         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10618                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10619         if (!(rsurface.ent_flags & RENDER_LIGHT))
10620                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10621         else if (FAKELIGHT_ENABLED)
10622         {
10623                         // no modellight if using fakelight for the map
10624         }
10625         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10626         {
10627                 // pick a model lighting mode
10628                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10629                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10630                 else
10631                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10632         }
10633         if (rsurface.ent_flags & RENDER_ADDITIVE)
10634                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10635         else if (t->currentalpha < 1)
10636                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10637         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10638                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10639         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10640                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10641         if (t->backgroundnumskinframes)
10642                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10643         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10644         {
10645                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10646                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10647         }
10648         else
10649                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10650         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10651                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10652
10653         // there is no tcmod
10654         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10655         {
10656                 t->currenttexmatrix = r_waterscrollmatrix;
10657                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10658         }
10659         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10660         {
10661                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10662                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10663         }
10664
10665         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10666                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10667         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10668                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10669
10670         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10671         if (t->currentskinframe->qpixels)
10672                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10673         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10674         if (!t->basetexture)
10675                 t->basetexture = r_texture_notexture;
10676         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10677         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10678         t->nmaptexture = t->currentskinframe->nmap;
10679         if (!t->nmaptexture)
10680                 t->nmaptexture = r_texture_blanknormalmap;
10681         t->glosstexture = r_texture_black;
10682         t->glowtexture = t->currentskinframe->glow;
10683         t->fogtexture = t->currentskinframe->fog;
10684         t->reflectmasktexture = t->currentskinframe->reflect;
10685         if (t->backgroundnumskinframes)
10686         {
10687                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10688                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10689                 t->backgroundglosstexture = r_texture_black;
10690                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10691                 if (!t->backgroundnmaptexture)
10692                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10693         }
10694         else
10695         {
10696                 t->backgroundbasetexture = r_texture_white;
10697                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10698                 t->backgroundglosstexture = r_texture_black;
10699                 t->backgroundglowtexture = NULL;
10700         }
10701         t->specularpower = r_shadow_glossexponent.value;
10702         // TODO: store reference values for these in the texture?
10703         t->specularscale = 0;
10704         if (r_shadow_gloss.integer > 0)
10705         {
10706                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10707                 {
10708                         if (r_shadow_glossintensity.value > 0)
10709                         {
10710                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10711                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10712                                 t->specularscale = r_shadow_glossintensity.value;
10713                         }
10714                 }
10715                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10716                 {
10717                         t->glosstexture = r_texture_white;
10718                         t->backgroundglosstexture = r_texture_white;
10719                         t->specularscale = r_shadow_gloss2intensity.value;
10720                         t->specularpower = r_shadow_gloss2exponent.value;
10721                 }
10722         }
10723         t->specularscale *= t->specularscalemod;
10724         t->specularpower *= t->specularpowermod;
10725
10726         // lightmaps mode looks bad with dlights using actual texturing, so turn
10727         // off the colormap and glossmap, but leave the normalmap on as it still
10728         // accurately represents the shading involved
10729         if (gl_lightmaps.integer)
10730         {
10731                 t->basetexture = r_texture_grey128;
10732                 t->pantstexture = r_texture_black;
10733                 t->shirttexture = r_texture_black;
10734                 t->nmaptexture = r_texture_blanknormalmap;
10735                 t->glosstexture = r_texture_black;
10736                 t->glowtexture = NULL;
10737                 t->fogtexture = NULL;
10738                 t->reflectmasktexture = NULL;
10739                 t->backgroundbasetexture = NULL;
10740                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10741                 t->backgroundglosstexture = r_texture_black;
10742                 t->backgroundglowtexture = NULL;
10743                 t->specularscale = 0;
10744                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10745         }
10746
10747         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10748         VectorClear(t->dlightcolor);
10749         t->currentnumlayers = 0;
10750         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10751         {
10752                 int blendfunc1, blendfunc2;
10753                 qboolean depthmask;
10754                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10755                 {
10756                         blendfunc1 = GL_SRC_ALPHA;
10757                         blendfunc2 = GL_ONE;
10758                 }
10759                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10760                 {
10761                         blendfunc1 = GL_SRC_ALPHA;
10762                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10763                 }
10764                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10765                 {
10766                         blendfunc1 = t->customblendfunc[0];
10767                         blendfunc2 = t->customblendfunc[1];
10768                 }
10769                 else
10770                 {
10771                         blendfunc1 = GL_ONE;
10772                         blendfunc2 = GL_ZERO;
10773                 }
10774                 // don't colormod evilblend textures
10775                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10776                         VectorSet(t->lightmapcolor, 1, 1, 1);
10777                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10778                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10779                 {
10780                         // fullbright is not affected by r_refdef.lightmapintensity
10781                         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]);
10782                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10783                                 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]);
10784                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10785                                 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]);
10786                 }
10787                 else
10788                 {
10789                         vec3_t ambientcolor;
10790                         float colorscale;
10791                         // set the color tint used for lights affecting this surface
10792                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10793                         colorscale = 2;
10794                         // q3bsp has no lightmap updates, so the lightstylevalue that
10795                         // would normally be baked into the lightmap must be
10796                         // applied to the color
10797                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10798                         if (model->type == mod_brushq3)
10799                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10800                         colorscale *= r_refdef.lightmapintensity;
10801                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10802                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10803                         // basic lit geometry
10804                         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]);
10805                         // add pants/shirt if needed
10806                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10807                                 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]);
10808                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10809                                 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]);
10810                         // now add ambient passes if needed
10811                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10812                         {
10813                                 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]);
10814                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10815                                         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]);
10816                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10817                                         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]);
10818                         }
10819                 }
10820                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10821                         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]);
10822                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10823                 {
10824                         // if this is opaque use alpha blend which will darken the earlier
10825                         // passes cheaply.
10826                         //
10827                         // if this is an alpha blended material, all the earlier passes
10828                         // were darkened by fog already, so we only need to add the fog
10829                         // color ontop through the fog mask texture
10830                         //
10831                         // if this is an additive blended material, all the earlier passes
10832                         // were darkened by fog already, and we should not add fog color
10833                         // (because the background was not darkened, there is no fog color
10834                         // that was lost behind it).
10835                         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]);
10836                 }
10837         }
10838
10839         return t->currentframe;
10840 }
10841
10842 rsurfacestate_t rsurface;
10843
10844 void R_Mesh_ResizeArrays(int newvertices)
10845 {
10846         unsigned char *base;
10847         size_t size;
10848         if (rsurface.array_size >= newvertices)
10849                 return;
10850         if (rsurface.array_base)
10851                 Mem_Free(rsurface.array_base);
10852         rsurface.array_size = (newvertices + 1023) & ~1023;
10853         size = 0;
10854         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10855         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10856         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10857         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10858         size += rsurface.array_size * sizeof(float[3]);
10859         size += rsurface.array_size * sizeof(float[3]);
10860         size += rsurface.array_size * sizeof(float[3]);
10861         size += rsurface.array_size * sizeof(float[3]);
10862         size += rsurface.array_size * sizeof(float[3]);
10863         size += rsurface.array_size * sizeof(float[3]);
10864         size += rsurface.array_size * sizeof(float[3]);
10865         size += rsurface.array_size * sizeof(float[3]);
10866         size += rsurface.array_size * sizeof(float[4]);
10867         size += rsurface.array_size * sizeof(float[2]);
10868         size += rsurface.array_size * sizeof(float[2]);
10869         size += rsurface.array_size * sizeof(float[4]);
10870         size += rsurface.array_size * sizeof(int[3]);
10871         size += rsurface.array_size * sizeof(unsigned short[3]);
10872         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10873         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10874         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10875         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10876         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10877         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10878         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10879         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10880         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10881         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10882         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10883         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10884         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10885         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10886         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10887         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10888         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10889         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
10890         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10891 }
10892
10893 void RSurf_ActiveWorldEntity(void)
10894 {
10895         int newvertices;
10896         dp_model_t *model = r_refdef.scene.worldmodel;
10897         //if (rsurface.entity == r_refdef.scene.worldentity)
10898         //      return;
10899         rsurface.entity = r_refdef.scene.worldentity;
10900         rsurface.skeleton = NULL;
10901         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10902         rsurface.ent_skinnum = 0;
10903         rsurface.ent_qwskin = -1;
10904         rsurface.ent_shadertime = 0;
10905         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10906         newvertices = max(model->surfmesh.num_vertices, model->surfmesh.num_triangles);
10907         if (rsurface.array_size < newvertices)
10908                 R_Mesh_ResizeArrays(newvertices);
10909         rsurface.matrix = identitymatrix;
10910         rsurface.inversematrix = identitymatrix;
10911         rsurface.matrixscale = 1;
10912         rsurface.inversematrixscale = 1;
10913         R_EntityMatrix(&identitymatrix);
10914         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10915         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10916         rsurface.fograngerecip = r_refdef.fograngerecip;
10917         rsurface.fogheightfade = r_refdef.fogheightfade;
10918         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10919         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10920         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10921         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10922         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10923         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10924         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10925         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10926         rsurface.colormod[3] = 1;
10927         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);
10928         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10929         rsurface.frameblend[0].lerp = 1;
10930         rsurface.ent_alttextures = false;
10931         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10932         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10933         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10934         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10935         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10936         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10937         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10938         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10939         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10940         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10941         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10942         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10943         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10944         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10945         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10946         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10947         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10948         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10949         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10950         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10951         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10952         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10953         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10954         rsurface.modelelement3i = model->surfmesh.data_element3i;
10955         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10956         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10957         rsurface.modelelement3s = model->surfmesh.data_element3s;
10958         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10959         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10960         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10961         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10962         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10963         rsurface.modelsurfaces = model->data_surfaces;
10964         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10965         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10966         rsurface.modelvertexposition = model->surfmesh.vertexposition;
10967         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10968         rsurface.modelgeneratedvertex = false;
10969         rsurface.batchgeneratedvertex = false;
10970         rsurface.batchfirstvertex = 0;
10971         rsurface.batchnumvertices = 0;
10972         rsurface.batchfirsttriangle = 0;
10973         rsurface.batchnumtriangles = 0;
10974         rsurface.batchvertex3f  = NULL;
10975         rsurface.batchvertex3f_vertexbuffer = NULL;
10976         rsurface.batchvertex3f_bufferoffset = 0;
10977         rsurface.batchsvector3f = NULL;
10978         rsurface.batchsvector3f_vertexbuffer = NULL;
10979         rsurface.batchsvector3f_bufferoffset = 0;
10980         rsurface.batchtvector3f = NULL;
10981         rsurface.batchtvector3f_vertexbuffer = NULL;
10982         rsurface.batchtvector3f_bufferoffset = 0;
10983         rsurface.batchnormal3f  = NULL;
10984         rsurface.batchnormal3f_vertexbuffer = NULL;
10985         rsurface.batchnormal3f_bufferoffset = 0;
10986         rsurface.batchlightmapcolor4f = NULL;
10987         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10988         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10989         rsurface.batchtexcoordtexture2f = NULL;
10990         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10991         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10992         rsurface.batchtexcoordlightmap2f = NULL;
10993         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10994         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10995         rsurface.batchvertexmesh = NULL;
10996         rsurface.batchvertexmeshbuffer = NULL;
10997         rsurface.batchvertexposition = NULL;
10998         rsurface.batchvertexpositionbuffer = NULL;
10999         rsurface.batchelement3i = NULL;
11000         rsurface.batchelement3i_indexbuffer = NULL;
11001         rsurface.batchelement3i_bufferoffset = 0;
11002         rsurface.batchelement3s = NULL;
11003         rsurface.batchelement3s_indexbuffer = NULL;
11004         rsurface.batchelement3s_bufferoffset = 0;
11005         rsurface.passcolor4f = NULL;
11006         rsurface.passcolor4f_vertexbuffer = NULL;
11007         rsurface.passcolor4f_bufferoffset = 0;
11008 }
11009
11010 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
11011 {
11012         int newvertices;
11013         dp_model_t *model = ent->model;
11014         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
11015         //      return;
11016         rsurface.entity = (entity_render_t *)ent;
11017         rsurface.skeleton = ent->skeleton;
11018         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
11019         rsurface.ent_skinnum = ent->skinnum;
11020         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;
11021         rsurface.ent_shadertime = ent->shadertime;
11022         rsurface.ent_flags = ent->flags;
11023         newvertices = max(model->surfmesh.num_vertices, model->surfmesh.num_triangles);
11024         if (rsurface.array_size < newvertices)
11025                 R_Mesh_ResizeArrays(newvertices);
11026         rsurface.matrix = ent->matrix;
11027         rsurface.inversematrix = ent->inversematrix;
11028         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11029         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11030         R_EntityMatrix(&rsurface.matrix);
11031         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11032         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11033         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11034         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11035         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11036         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11037         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
11038         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
11039         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
11040         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
11041         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
11042         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
11043         rsurface.colormod[3] = ent->alpha;
11044         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
11045         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
11046         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
11047         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11048         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11049         if (ent->model->brush.submodel && !prepass)
11050         {
11051                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
11052                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
11053         }
11054         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
11055         {
11056                 if (ent->animcache_vertex3f && !r_framedata_failed)
11057                 {
11058                         rsurface.modelvertex3f = ent->animcache_vertex3f;
11059                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
11060                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
11061                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
11062                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
11063                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
11064                         rsurface.modelvertexposition = ent->animcache_vertexposition;
11065                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
11066                 }
11067                 else if (wanttangents)
11068                 {
11069                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11070                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11071                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11072                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11073                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
11074                         rsurface.modelvertexmesh = NULL;
11075                         rsurface.modelvertexmeshbuffer = NULL;
11076                         rsurface.modelvertexposition = NULL;
11077                         rsurface.modelvertexpositionbuffer = NULL;
11078                 }
11079                 else if (wantnormals)
11080                 {
11081                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11082                         rsurface.modelsvector3f = NULL;
11083                         rsurface.modeltvector3f = NULL;
11084                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11085                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
11086                         rsurface.modelvertexmesh = NULL;
11087                         rsurface.modelvertexmeshbuffer = NULL;
11088                         rsurface.modelvertexposition = NULL;
11089                         rsurface.modelvertexpositionbuffer = NULL;
11090                 }
11091                 else
11092                 {
11093                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11094                         rsurface.modelsvector3f = NULL;
11095                         rsurface.modeltvector3f = NULL;
11096                         rsurface.modelnormal3f = NULL;
11097                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
11098                         rsurface.modelvertexmesh = NULL;
11099                         rsurface.modelvertexmeshbuffer = NULL;
11100                         rsurface.modelvertexposition = NULL;
11101                         rsurface.modelvertexpositionbuffer = NULL;
11102                 }
11103                 rsurface.modelvertex3f_vertexbuffer = 0;
11104                 rsurface.modelvertex3f_bufferoffset = 0;
11105                 rsurface.modelsvector3f_vertexbuffer = 0;
11106                 rsurface.modelsvector3f_bufferoffset = 0;
11107                 rsurface.modeltvector3f_vertexbuffer = 0;
11108                 rsurface.modeltvector3f_bufferoffset = 0;
11109                 rsurface.modelnormal3f_vertexbuffer = 0;
11110                 rsurface.modelnormal3f_bufferoffset = 0;
11111                 rsurface.modelgeneratedvertex = true;
11112         }
11113         else
11114         {
11115                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
11116                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11117                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11118                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11119                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11120                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11121                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11122                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11123                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11124                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
11125                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11126                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11127                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11128                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11129                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
11130                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
11131                 rsurface.modelgeneratedvertex = false;
11132         }
11133         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11134         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11135         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11136         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11137         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11138         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11139         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11140         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11141         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11142         rsurface.modelelement3i = model->surfmesh.data_element3i;
11143         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11144         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11145         rsurface.modelelement3s = model->surfmesh.data_element3s;
11146         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11147         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11148         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11149         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11150         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11151         rsurface.modelsurfaces = model->data_surfaces;
11152         rsurface.batchgeneratedvertex = false;
11153         rsurface.batchfirstvertex = 0;
11154         rsurface.batchnumvertices = 0;
11155         rsurface.batchfirsttriangle = 0;
11156         rsurface.batchnumtriangles = 0;
11157         rsurface.batchvertex3f  = NULL;
11158         rsurface.batchvertex3f_vertexbuffer = NULL;
11159         rsurface.batchvertex3f_bufferoffset = 0;
11160         rsurface.batchsvector3f = NULL;
11161         rsurface.batchsvector3f_vertexbuffer = NULL;
11162         rsurface.batchsvector3f_bufferoffset = 0;
11163         rsurface.batchtvector3f = NULL;
11164         rsurface.batchtvector3f_vertexbuffer = NULL;
11165         rsurface.batchtvector3f_bufferoffset = 0;
11166         rsurface.batchnormal3f  = NULL;
11167         rsurface.batchnormal3f_vertexbuffer = NULL;
11168         rsurface.batchnormal3f_bufferoffset = 0;
11169         rsurface.batchlightmapcolor4f = NULL;
11170         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11171         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11172         rsurface.batchtexcoordtexture2f = NULL;
11173         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11174         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11175         rsurface.batchtexcoordlightmap2f = NULL;
11176         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11177         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11178         rsurface.batchvertexmesh = NULL;
11179         rsurface.batchvertexmeshbuffer = NULL;
11180         rsurface.batchvertexposition = NULL;
11181         rsurface.batchvertexpositionbuffer = NULL;
11182         rsurface.batchelement3i = NULL;
11183         rsurface.batchelement3i_indexbuffer = NULL;
11184         rsurface.batchelement3i_bufferoffset = 0;
11185         rsurface.batchelement3s = NULL;
11186         rsurface.batchelement3s_indexbuffer = NULL;
11187         rsurface.batchelement3s_bufferoffset = 0;
11188         rsurface.passcolor4f = NULL;
11189         rsurface.passcolor4f_vertexbuffer = NULL;
11190         rsurface.passcolor4f_bufferoffset = 0;
11191 }
11192
11193 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)
11194 {
11195         int newvertices;
11196
11197         rsurface.entity = r_refdef.scene.worldentity;
11198         rsurface.skeleton = NULL;
11199         rsurface.ent_skinnum = 0;
11200         rsurface.ent_qwskin = -1;
11201         rsurface.ent_shadertime = shadertime;
11202         rsurface.ent_flags = entflags;
11203         rsurface.modelnumvertices = numvertices;
11204         rsurface.modelnumtriangles = numtriangles;
11205         newvertices = max(rsurface.modelnumvertices, rsurface.modelnumtriangles);
11206         if (rsurface.array_size < newvertices)
11207                 R_Mesh_ResizeArrays(newvertices);
11208         rsurface.matrix = *matrix;
11209         rsurface.inversematrix = *inversematrix;
11210         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11211         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11212         R_EntityMatrix(&rsurface.matrix);
11213         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11214         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11215         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11216         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11217         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11218         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11219         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11220         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11221         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11222         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11223         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11224         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11225         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);
11226         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11227         rsurface.frameblend[0].lerp = 1;
11228         rsurface.ent_alttextures = false;
11229         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11230         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11231         if (wanttangents)
11232         {
11233                 rsurface.modelvertex3f = vertex3f;
11234                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
11235                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
11236                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11237         }
11238         else if (wantnormals)
11239         {
11240                 rsurface.modelvertex3f = vertex3f;
11241                 rsurface.modelsvector3f = NULL;
11242                 rsurface.modeltvector3f = NULL;
11243                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11244         }
11245         else
11246         {
11247                 rsurface.modelvertex3f = vertex3f;
11248                 rsurface.modelsvector3f = NULL;
11249                 rsurface.modeltvector3f = NULL;
11250                 rsurface.modelnormal3f = NULL;
11251         }
11252         rsurface.modelvertexmesh = NULL;
11253         rsurface.modelvertexmeshbuffer = NULL;
11254         rsurface.modelvertexposition = NULL;
11255         rsurface.modelvertexpositionbuffer = NULL;
11256         rsurface.modelvertex3f_vertexbuffer = 0;
11257         rsurface.modelvertex3f_bufferoffset = 0;
11258         rsurface.modelsvector3f_vertexbuffer = 0;
11259         rsurface.modelsvector3f_bufferoffset = 0;
11260         rsurface.modeltvector3f_vertexbuffer = 0;
11261         rsurface.modeltvector3f_bufferoffset = 0;
11262         rsurface.modelnormal3f_vertexbuffer = 0;
11263         rsurface.modelnormal3f_bufferoffset = 0;
11264         rsurface.modelgeneratedvertex = true;
11265         rsurface.modellightmapcolor4f  = color4f;
11266         rsurface.modellightmapcolor4f_vertexbuffer = 0;
11267         rsurface.modellightmapcolor4f_bufferoffset = 0;
11268         rsurface.modeltexcoordtexture2f  = texcoord2f;
11269         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11270         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11271         rsurface.modeltexcoordlightmap2f  = NULL;
11272         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11273         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11274         rsurface.modelelement3i = element3i;
11275         rsurface.modelelement3i_indexbuffer = NULL;
11276         rsurface.modelelement3i_bufferoffset = 0;
11277         rsurface.modelelement3s = element3s;
11278         rsurface.modelelement3s_indexbuffer = NULL;
11279         rsurface.modelelement3s_bufferoffset = 0;
11280         rsurface.modellightmapoffsets = NULL;
11281         rsurface.modelsurfaces = NULL;
11282         rsurface.batchgeneratedvertex = false;
11283         rsurface.batchfirstvertex = 0;
11284         rsurface.batchnumvertices = 0;
11285         rsurface.batchfirsttriangle = 0;
11286         rsurface.batchnumtriangles = 0;
11287         rsurface.batchvertex3f  = NULL;
11288         rsurface.batchvertex3f_vertexbuffer = NULL;
11289         rsurface.batchvertex3f_bufferoffset = 0;
11290         rsurface.batchsvector3f = NULL;
11291         rsurface.batchsvector3f_vertexbuffer = NULL;
11292         rsurface.batchsvector3f_bufferoffset = 0;
11293         rsurface.batchtvector3f = NULL;
11294         rsurface.batchtvector3f_vertexbuffer = NULL;
11295         rsurface.batchtvector3f_bufferoffset = 0;
11296         rsurface.batchnormal3f  = NULL;
11297         rsurface.batchnormal3f_vertexbuffer = NULL;
11298         rsurface.batchnormal3f_bufferoffset = 0;
11299         rsurface.batchlightmapcolor4f = NULL;
11300         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11301         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11302         rsurface.batchtexcoordtexture2f = NULL;
11303         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11304         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11305         rsurface.batchtexcoordlightmap2f = NULL;
11306         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11307         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11308         rsurface.batchvertexmesh = NULL;
11309         rsurface.batchvertexmeshbuffer = NULL;
11310         rsurface.batchvertexposition = NULL;
11311         rsurface.batchvertexpositionbuffer = NULL;
11312         rsurface.batchelement3i = NULL;
11313         rsurface.batchelement3i_indexbuffer = NULL;
11314         rsurface.batchelement3i_bufferoffset = 0;
11315         rsurface.batchelement3s = NULL;
11316         rsurface.batchelement3s_indexbuffer = NULL;
11317         rsurface.batchelement3s_bufferoffset = 0;
11318         rsurface.passcolor4f = NULL;
11319         rsurface.passcolor4f_vertexbuffer = NULL;
11320         rsurface.passcolor4f_bufferoffset = 0;
11321
11322         if (rsurface.modelnumvertices && rsurface.modelelement3i)
11323         {
11324                 if ((wantnormals || wanttangents) && !normal3f)
11325                 {
11326                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11327                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11328                 }
11329                 if (wanttangents && !svector3f)
11330                 {
11331                         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);
11332                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11333                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11334                 }
11335         }
11336 }
11337
11338 float RSurf_FogPoint(const float *v)
11339 {
11340         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11341         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11342         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11343         float FogHeightFade = r_refdef.fogheightfade;
11344         float fogfrac;
11345         unsigned int fogmasktableindex;
11346         if (r_refdef.fogplaneviewabove)
11347                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11348         else
11349                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11350         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11351         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11352 }
11353
11354 float RSurf_FogVertex(const float *v)
11355 {
11356         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11357         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11358         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11359         float FogHeightFade = rsurface.fogheightfade;
11360         float fogfrac;
11361         unsigned int fogmasktableindex;
11362         if (r_refdef.fogplaneviewabove)
11363                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11364         else
11365                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11366         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11367         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11368 }
11369
11370 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11371 {
11372         int i;
11373         for (i = 0;i < numelements;i++)
11374                 outelement3i[i] = inelement3i[i] + adjust;
11375 }
11376
11377 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11378 extern cvar_t gl_vbo;
11379 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11380 {
11381         int deformindex;
11382         int firsttriangle;
11383         int numtriangles;
11384         int firstvertex;
11385         int endvertex;
11386         int numvertices;
11387         int surfacefirsttriangle;
11388         int surfacenumtriangles;
11389         int surfacefirstvertex;
11390         int surfaceendvertex;
11391         int surfacenumvertices;
11392         int needsupdate;
11393         int i, j;
11394         qboolean gaps;
11395         qboolean dynamicvertex;
11396         float amplitude;
11397         float animpos;
11398         float scale;
11399         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11400         float waveparms[4];
11401         q3shaderinfo_deform_t *deform;
11402         const msurface_t *surface, *firstsurface;
11403         r_vertexposition_t *vertexposition;
11404         r_vertexmesh_t *vertexmesh;
11405         if (!texturenumsurfaces)
11406                 return;
11407         // find vertex range of this surface batch
11408         gaps = false;
11409         firstsurface = texturesurfacelist[0];
11410         firsttriangle = firstsurface->num_firsttriangle;
11411         numtriangles = 0;
11412         firstvertex = endvertex = firstsurface->num_firstvertex;
11413         for (i = 0;i < texturenumsurfaces;i++)
11414         {
11415                 surface = texturesurfacelist[i];
11416                 if (surface != firstsurface + i)
11417                         gaps = true;
11418                 surfacefirstvertex = surface->num_firstvertex;
11419                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11420                 surfacenumtriangles = surface->num_triangles;
11421                 if (firstvertex > surfacefirstvertex)
11422                         firstvertex = surfacefirstvertex;
11423                 if (endvertex < surfaceendvertex)
11424                         endvertex = surfaceendvertex;
11425                 numtriangles += surfacenumtriangles;
11426         }
11427
11428         // we now know the vertex range used, and if there are any gaps in it
11429         rsurface.batchfirstvertex = firstvertex;
11430         rsurface.batchnumvertices = endvertex - firstvertex;
11431         rsurface.batchfirsttriangle = firsttriangle;
11432         rsurface.batchnumtriangles = numtriangles;
11433
11434         // this variable holds flags for which properties have been updated that
11435         // may require regenerating vertexmesh or vertexposition arrays...
11436         needsupdate = 0;
11437
11438         // check if any dynamic vertex processing must occur
11439         dynamicvertex = false;
11440
11441         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11442                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11443         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11444         {
11445                 switch (deform->deform)
11446                 {
11447                 default:
11448                 case Q3DEFORM_PROJECTIONSHADOW:
11449                 case Q3DEFORM_TEXT0:
11450                 case Q3DEFORM_TEXT1:
11451                 case Q3DEFORM_TEXT2:
11452                 case Q3DEFORM_TEXT3:
11453                 case Q3DEFORM_TEXT4:
11454                 case Q3DEFORM_TEXT5:
11455                 case Q3DEFORM_TEXT6:
11456                 case Q3DEFORM_TEXT7:
11457                 case Q3DEFORM_NONE:
11458                         break;
11459                 case Q3DEFORM_AUTOSPRITE:
11460                         dynamicvertex = true;
11461                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11462                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11463                         break;
11464                 case Q3DEFORM_AUTOSPRITE2:
11465                         dynamicvertex = true;
11466                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11467                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11468                         break;
11469                 case Q3DEFORM_NORMAL:
11470                         dynamicvertex = true;
11471                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11472                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11473                         break;
11474                 case Q3DEFORM_WAVE:
11475                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11476                                 break; // if wavefunc is a nop, ignore this transform
11477                         dynamicvertex = true;
11478                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11479                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11480                         break;
11481                 case Q3DEFORM_BULGE:
11482                         dynamicvertex = true;
11483                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11484                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11485                         break;
11486                 case Q3DEFORM_MOVE:
11487                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11488                                 break; // if wavefunc is a nop, ignore this transform
11489                         dynamicvertex = true;
11490                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11491                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11492                         break;
11493                 }
11494         }
11495         switch(rsurface.texture->tcgen.tcgen)
11496         {
11497         default:
11498         case Q3TCGEN_TEXTURE:
11499                 break;
11500         case Q3TCGEN_LIGHTMAP:
11501                 dynamicvertex = true;
11502                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11503                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11504                 break;
11505         case Q3TCGEN_VECTOR:
11506                 dynamicvertex = true;
11507                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11508                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11509                 break;
11510         case Q3TCGEN_ENVIRONMENT:
11511                 dynamicvertex = true;
11512                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11513                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11514                 break;
11515         }
11516         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11517         {
11518                 dynamicvertex = true;
11519                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11520                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11521         }
11522
11523         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11524         {
11525                 dynamicvertex = true;
11526                 batchneed |= BATCHNEED_NOGAPS;
11527                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11528         }
11529
11530         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11531         {
11532                 dynamicvertex = true;
11533                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11534                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11535         }
11536
11537         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11538         {
11539                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11540                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11541                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11542                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11543                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11544                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11545                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11546         }
11547
11548         // when the model data has no vertex buffer (dynamic mesh), we need to
11549         // eliminate gaps
11550         if (!rsurface.modelvertexmeshbuffer)
11551                 batchneed |= BATCHNEED_NOGAPS;
11552
11553         // if needsupdate, we have to do a dynamic vertex batch for sure
11554         if (needsupdate & batchneed)
11555                 dynamicvertex = true;
11556
11557         // see if we need to build vertexmesh from arrays
11558         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11559                 dynamicvertex = true;
11560
11561         // see if we need to build vertexposition from arrays
11562         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11563                 dynamicvertex = true;
11564
11565         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11566         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11567                 dynamicvertex = true;
11568
11569         // if there is a chance of animated vertex colors, it's a dynamic batch
11570         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11571                 dynamicvertex = true;
11572
11573         rsurface.batchvertex3f = rsurface.modelvertex3f;
11574         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11575         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11576         rsurface.batchsvector3f = rsurface.modelsvector3f;
11577         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11578         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11579         rsurface.batchtvector3f = rsurface.modeltvector3f;
11580         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11581         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11582         rsurface.batchnormal3f = rsurface.modelnormal3f;
11583         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11584         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11585         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11586         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11587         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11588         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11589         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11590         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11591         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11592         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11593         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11594         rsurface.batchvertexposition = rsurface.modelvertexposition;
11595         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11596         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11597         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11598         rsurface.batchelement3i = rsurface.modelelement3i;
11599         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11600         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11601         rsurface.batchelement3s = rsurface.modelelement3s;
11602         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11603         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11604
11605         // if any dynamic vertex processing has to occur in software, we copy the
11606         // entire surface list together before processing to rebase the vertices
11607         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11608         //
11609         // if any gaps exist and we do not have a static vertex buffer, we have to
11610         // copy the surface list together to avoid wasting upload bandwidth on the
11611         // vertices in the gaps.
11612         //
11613         // if gaps exist and we have a static vertex buffer, we still have to
11614         // combine the index buffer ranges into one dynamic index buffer.
11615         //
11616         // in all cases we end up with data that can be drawn in one call.
11617
11618         if (!dynamicvertex)
11619         {
11620                 // static vertex data, just set pointers...
11621                 rsurface.batchgeneratedvertex = false;
11622                 // if there are gaps, we want to build a combined index buffer,
11623                 // otherwise use the original static buffer with an appropriate offset
11624                 if (gaps)
11625                 {
11626                         firsttriangle = 0;
11627                         numtriangles = 0;
11628                         for (i = 0;i < texturenumsurfaces;i++)
11629                         {
11630                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11631                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11632                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11633                                 numtriangles += surfacenumtriangles;
11634                         }
11635                         rsurface.batchelement3i = rsurface.array_batchelement3i;
11636                         rsurface.batchelement3i_indexbuffer = NULL;
11637                         rsurface.batchelement3i_bufferoffset = 0;
11638                         rsurface.batchelement3s = NULL;
11639                         rsurface.batchelement3s_indexbuffer = NULL;
11640                         rsurface.batchelement3s_bufferoffset = 0;
11641                         if (endvertex <= 65536)
11642                         {
11643                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
11644                                 for (i = 0;i < numtriangles*3;i++)
11645                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11646                         }
11647                         rsurface.batchfirsttriangle = firsttriangle;
11648                         rsurface.batchnumtriangles = numtriangles;
11649                 }
11650                 return;
11651         }
11652
11653         // something needs software processing, do it for real...
11654         // we only directly handle interleaved array data in this case...
11655         rsurface.batchgeneratedvertex = true;
11656
11657         // now copy the vertex data into a combined array and make an index array
11658         // (this is what Quake3 does all the time)
11659         //if (gaps || rsurface.batchfirstvertex)
11660         {
11661                 rsurface.batchvertexposition = NULL;
11662                 rsurface.batchvertexpositionbuffer = NULL;
11663                 rsurface.batchvertexmesh = NULL;
11664                 rsurface.batchvertexmeshbuffer = NULL;
11665                 rsurface.batchvertex3f = NULL;
11666                 rsurface.batchvertex3f_vertexbuffer = NULL;
11667                 rsurface.batchvertex3f_bufferoffset = 0;
11668                 rsurface.batchsvector3f = NULL;
11669                 rsurface.batchsvector3f_vertexbuffer = NULL;
11670                 rsurface.batchsvector3f_bufferoffset = 0;
11671                 rsurface.batchtvector3f = NULL;
11672                 rsurface.batchtvector3f_vertexbuffer = NULL;
11673                 rsurface.batchtvector3f_bufferoffset = 0;
11674                 rsurface.batchnormal3f = NULL;
11675                 rsurface.batchnormal3f_vertexbuffer = NULL;
11676                 rsurface.batchnormal3f_bufferoffset = 0;
11677                 rsurface.batchlightmapcolor4f = NULL;
11678                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11679                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11680                 rsurface.batchtexcoordtexture2f = NULL;
11681                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11682                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11683                 rsurface.batchtexcoordlightmap2f = NULL;
11684                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11685                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11686                 rsurface.batchelement3i = rsurface.array_batchelement3i;
11687                 rsurface.batchelement3i_indexbuffer = NULL;
11688                 rsurface.batchelement3i_bufferoffset = 0;
11689                 rsurface.batchelement3s = NULL;
11690                 rsurface.batchelement3s_indexbuffer = NULL;
11691                 rsurface.batchelement3s_bufferoffset = 0;
11692                 // we'll only be setting up certain arrays as needed
11693                 if (batchneed & BATCHNEED_VERTEXPOSITION)
11694                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11695                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11696                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11697                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11698                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11699                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11700                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11701                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11702                 {
11703                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11704                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11705                 }
11706                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11707                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11708                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11709                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11710                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11711                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11712                 numvertices = 0;
11713                 numtriangles = 0;
11714                 for (i = 0;i < texturenumsurfaces;i++)
11715                 {
11716                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11717                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11718                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11719                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11720                         // copy only the data requested
11721                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11722                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11723                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11724                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11725                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11726                         {
11727                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11728                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11729                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11730                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11731                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11732                                 {
11733                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11734                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11735                                 }
11736                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11737                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11738                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11739                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11740                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11741                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11742                         }
11743                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11744                         numvertices += surfacenumvertices;
11745                         numtriangles += surfacenumtriangles;
11746                 }
11747
11748                 // generate a 16bit index array as well if possible
11749                 // (in general, dynamic batches fit)
11750                 if (numvertices <= 65536)
11751                 {
11752                         rsurface.batchelement3s = rsurface.array_batchelement3s;
11753                         for (i = 0;i < numtriangles*3;i++)
11754                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11755                 }
11756
11757                 // since we've copied everything, the batch now starts at 0
11758                 rsurface.batchfirstvertex = 0;
11759                 rsurface.batchnumvertices = numvertices;
11760                 rsurface.batchfirsttriangle = 0;
11761                 rsurface.batchnumtriangles = numtriangles;
11762         }
11763
11764         // q1bsp surfaces rendered in vertex color mode have to have colors
11765         // calculated based on lightstyles
11766         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11767         {
11768                 // generate color arrays for the surfaces in this list
11769                 int c[4];
11770                 int scale;
11771                 int size3;
11772                 const int *offsets;
11773                 const unsigned char *lm;
11774                 numvertices = 0;
11775                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11776                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11777                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11778                 for (i = 0;i < texturenumsurfaces;i++)
11779                 {
11780                         surface = texturesurfacelist[i];
11781                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11782                         surfacenumvertices = surface->num_vertices;
11783                         if (surface->lightmapinfo->samples)
11784                         {
11785                                 for (j = 0;j < surfacenumvertices;j++)
11786                                 {
11787                                         lm = surface->lightmapinfo->samples + offsets[j];
11788                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11789                                         VectorScale(lm, scale, c);
11790                                         if (surface->lightmapinfo->styles[1] != 255)
11791                                         {
11792                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11793                                                 lm += size3;
11794                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11795                                                 VectorMA(c, scale, lm, c);
11796                                                 if (surface->lightmapinfo->styles[2] != 255)
11797                                                 {
11798                                                         lm += size3;
11799                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11800                                                         VectorMA(c, scale, lm, c);
11801                                                         if (surface->lightmapinfo->styles[3] != 255)
11802                                                         {
11803                                                                 lm += size3;
11804                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11805                                                                 VectorMA(c, scale, lm, c);
11806                                                         }
11807                                                 }
11808                                         }
11809                                         c[0] >>= 15;
11810                                         c[1] >>= 15;
11811                                         c[2] >>= 15;
11812                                         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);
11813                                         numvertices++;
11814                                 }
11815                         }
11816                         else
11817                         {
11818                                 for (j = 0;j < surfacenumvertices;j++)
11819                                 {
11820                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11821                                         numvertices++;
11822                                 }
11823                         }
11824                 }
11825         }
11826
11827         // if vertices are deformed (sprite flares and things in maps, possibly
11828         // water waves, bulges and other deformations), modify the copied vertices
11829         // in place
11830         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11831         {
11832                 switch (deform->deform)
11833                 {
11834                 default:
11835                 case Q3DEFORM_PROJECTIONSHADOW:
11836                 case Q3DEFORM_TEXT0:
11837                 case Q3DEFORM_TEXT1:
11838                 case Q3DEFORM_TEXT2:
11839                 case Q3DEFORM_TEXT3:
11840                 case Q3DEFORM_TEXT4:
11841                 case Q3DEFORM_TEXT5:
11842                 case Q3DEFORM_TEXT6:
11843                 case Q3DEFORM_TEXT7:
11844                 case Q3DEFORM_NONE:
11845                         break;
11846                 case Q3DEFORM_AUTOSPRITE:
11847                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11848                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11849                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11850                         VectorNormalize(newforward);
11851                         VectorNormalize(newright);
11852                         VectorNormalize(newup);
11853                         // a single autosprite surface can contain multiple sprites...
11854                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11855                         {
11856                                 VectorClear(center);
11857                                 for (i = 0;i < 4;i++)
11858                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11859                                 VectorScale(center, 0.25f, center);
11860                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11861                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11862                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11863                                 for (i = 0;i < 4;i++)
11864                                 {
11865                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11866                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11867                                 }
11868                         }
11869                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11870                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11871                         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, r_smoothnormals_areaweighting.integer != 0);
11872                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11873                         rsurface.batchvertex3f_vertexbuffer = NULL;
11874                         rsurface.batchvertex3f_bufferoffset = 0;
11875                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11876                         rsurface.batchsvector3f_vertexbuffer = NULL;
11877                         rsurface.batchsvector3f_bufferoffset = 0;
11878                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11879                         rsurface.batchtvector3f_vertexbuffer = NULL;
11880                         rsurface.batchtvector3f_bufferoffset = 0;
11881                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11882                         rsurface.batchnormal3f_vertexbuffer = NULL;
11883                         rsurface.batchnormal3f_bufferoffset = 0;
11884                         break;
11885                 case Q3DEFORM_AUTOSPRITE2:
11886                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11887                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11888                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11889                         VectorNormalize(newforward);
11890                         VectorNormalize(newright);
11891                         VectorNormalize(newup);
11892                         {
11893                                 const float *v1, *v2;
11894                                 vec3_t start, end;
11895                                 float f, l;
11896                                 struct
11897                                 {
11898                                         float length2;
11899                                         const float *v1;
11900                                         const float *v2;
11901                                 }
11902                                 shortest[2];
11903                                 memset(shortest, 0, sizeof(shortest));
11904                                 // a single autosprite surface can contain multiple sprites...
11905                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11906                                 {
11907                                         VectorClear(center);
11908                                         for (i = 0;i < 4;i++)
11909                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11910                                         VectorScale(center, 0.25f, center);
11911                                         // find the two shortest edges, then use them to define the
11912                                         // axis vectors for rotating around the central axis
11913                                         for (i = 0;i < 6;i++)
11914                                         {
11915                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11916                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11917                                                 l = VectorDistance2(v1, v2);
11918                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11919                                                 if (v1[2] != v2[2])
11920                                                         l += (1.0f / 1024.0f);
11921                                                 if (shortest[0].length2 > l || i == 0)
11922                                                 {
11923                                                         shortest[1] = shortest[0];
11924                                                         shortest[0].length2 = l;
11925                                                         shortest[0].v1 = v1;
11926                                                         shortest[0].v2 = v2;
11927                                                 }
11928                                                 else if (shortest[1].length2 > l || i == 1)
11929                                                 {
11930                                                         shortest[1].length2 = l;
11931                                                         shortest[1].v1 = v1;
11932                                                         shortest[1].v2 = v2;
11933                                                 }
11934                                         }
11935                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11936                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11937                                         // this calculates the right vector from the shortest edge
11938                                         // and the up vector from the edge midpoints
11939                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11940                                         VectorNormalize(right);
11941                                         VectorSubtract(end, start, up);
11942                                         VectorNormalize(up);
11943                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11944                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11945                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11946                                         VectorNegate(forward, forward);
11947                                         VectorReflect(forward, 0, up, forward);
11948                                         VectorNormalize(forward);
11949                                         CrossProduct(up, forward, newright);
11950                                         VectorNormalize(newright);
11951                                         // rotate the quad around the up axis vector, this is made
11952                                         // especially easy by the fact we know the quad is flat,
11953                                         // so we only have to subtract the center position and
11954                                         // measure distance along the right vector, and then
11955                                         // multiply that by the newright vector and add back the
11956                                         // center position
11957                                         // we also need to subtract the old position to undo the
11958                                         // displacement from the center, which we do with a
11959                                         // DotProduct, the subtraction/addition of center is also
11960                                         // optimized into DotProducts here
11961                                         l = DotProduct(right, center);
11962                                         for (i = 0;i < 4;i++)
11963                                         {
11964                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11965                                                 f = DotProduct(right, v1) - l;
11966                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11967                                         }
11968                                 }
11969                         }
11970                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11971                         rsurface.batchvertex3f_vertexbuffer = NULL;
11972                         rsurface.batchvertex3f_bufferoffset = 0;
11973                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11974                         {
11975                                 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11976                                 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11977                                 rsurface.batchnormal3f_vertexbuffer = NULL;
11978                                 rsurface.batchnormal3f_bufferoffset = 0;
11979                         }
11980                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11981                         {
11982                                 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, r_smoothnormals_areaweighting.integer != 0);
11983                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11984                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11985                                 rsurface.batchsvector3f_bufferoffset = 0;
11986                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11987                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11988                                 rsurface.batchtvector3f_bufferoffset = 0;
11989                         }
11990                         break;
11991                 case Q3DEFORM_NORMAL:
11992                         // deform the normals to make reflections wavey
11993                         for (j = 0;j < rsurface.batchnumvertices;j++)
11994                         {
11995                                 float vertex[3];
11996                                 float *normal = rsurface.array_batchnormal3f + 3*j;
11997                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11998                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11999                                 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]);
12000                                 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]);
12001                                 VectorNormalize(normal);
12002                         }
12003                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12004                         rsurface.batchnormal3f_vertexbuffer = NULL;
12005                         rsurface.batchnormal3f_bufferoffset = 0;
12006                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12007                         {
12008                                 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, r_smoothnormals_areaweighting.integer != 0);
12009                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12010                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12011                                 rsurface.batchsvector3f_bufferoffset = 0;
12012                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12013                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12014                                 rsurface.batchtvector3f_bufferoffset = 0;
12015                         }
12016                         break;
12017                 case Q3DEFORM_WAVE:
12018                         // deform vertex array to make wavey water and flags and such
12019                         waveparms[0] = deform->waveparms[0];
12020                         waveparms[1] = deform->waveparms[1];
12021                         waveparms[2] = deform->waveparms[2];
12022                         waveparms[3] = deform->waveparms[3];
12023                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
12024                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12025                         // this is how a divisor of vertex influence on deformation
12026                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
12027                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12028                         for (j = 0;j < rsurface.batchnumvertices;j++)
12029                         {
12030                                 // if the wavefunc depends on time, evaluate it per-vertex
12031                                 if (waveparms[3])
12032                                 {
12033                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
12034                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12035                                 }
12036                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
12037                         }
12038                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12039                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12040                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12041                         rsurface.batchvertex3f_vertexbuffer = NULL;
12042                         rsurface.batchvertex3f_bufferoffset = 0;
12043                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12044                         rsurface.batchnormal3f_vertexbuffer = NULL;
12045                         rsurface.batchnormal3f_bufferoffset = 0;
12046                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12047                         {
12048                                 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, r_smoothnormals_areaweighting.integer != 0);
12049                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12050                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12051                                 rsurface.batchsvector3f_bufferoffset = 0;
12052                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12053                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12054                                 rsurface.batchtvector3f_bufferoffset = 0;
12055                         }
12056                         break;
12057                 case Q3DEFORM_BULGE:
12058                         // deform vertex array to make the surface have moving bulges
12059                         for (j = 0;j < rsurface.batchnumvertices;j++)
12060                         {
12061                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
12062                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
12063                         }
12064                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12065                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12066                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12067                         rsurface.batchvertex3f_vertexbuffer = NULL;
12068                         rsurface.batchvertex3f_bufferoffset = 0;
12069                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12070                         rsurface.batchnormal3f_vertexbuffer = NULL;
12071                         rsurface.batchnormal3f_bufferoffset = 0;
12072                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12073                         {
12074                                 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, r_smoothnormals_areaweighting.integer != 0);
12075                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12076                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12077                                 rsurface.batchsvector3f_bufferoffset = 0;
12078                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12079                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12080                                 rsurface.batchtvector3f_bufferoffset = 0;
12081                         }
12082                         break;
12083                 case Q3DEFORM_MOVE:
12084                         // deform vertex array
12085                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12086                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12087                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
12088                         VectorScale(deform->parms, scale, waveparms);
12089                         for (j = 0;j < rsurface.batchnumvertices;j++)
12090                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
12091                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12092                         rsurface.batchvertex3f_vertexbuffer = NULL;
12093                         rsurface.batchvertex3f_bufferoffset = 0;
12094                         break;
12095                 }
12096         }
12097
12098         // generate texcoords based on the chosen texcoord source
12099         switch(rsurface.texture->tcgen.tcgen)
12100         {
12101         default:
12102         case Q3TCGEN_TEXTURE:
12103                 break;
12104         case Q3TCGEN_LIGHTMAP:
12105                 if (rsurface.batchtexcoordlightmap2f)
12106                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
12107                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12108                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12109                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12110                 break;
12111         case Q3TCGEN_VECTOR:
12112                 for (j = 0;j < rsurface.batchnumvertices;j++)
12113                 {
12114                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12115                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12116                 }
12117                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12118                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12119                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12120                 break;
12121         case Q3TCGEN_ENVIRONMENT:
12122                 // make environment reflections using a spheremap
12123                 for (j = 0;j < rsurface.batchnumvertices;j++)
12124                 {
12125                         // identical to Q3A's method, but executed in worldspace so
12126                         // carried models can be shiny too
12127
12128                         float viewer[3], d, reflected[3], worldreflected[3];
12129
12130                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12131                         // VectorNormalize(viewer);
12132
12133                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12134
12135                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12136                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12137                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12138                         // note: this is proportinal to viewer, so we can normalize later
12139
12140                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12141                         VectorNormalize(worldreflected);
12142
12143                         // note: this sphere map only uses world x and z!
12144                         // so positive and negative y will LOOK THE SAME.
12145                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12146                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12147                 }
12148                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12149                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12150                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12151                 break;
12152         }
12153         // the only tcmod that needs software vertex processing is turbulent, so
12154         // check for it here and apply the changes if needed
12155         // and we only support that as the first one
12156         // (handling a mixture of turbulent and other tcmods would be problematic
12157         //  without punting it entirely to a software path)
12158         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12159         {
12160                 amplitude = rsurface.texture->tcmods[0].parms[1];
12161                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12162                 for (j = 0;j < rsurface.batchnumvertices;j++)
12163                 {
12164                         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);
12165                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12166                 }
12167                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12168                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12169                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12170         }
12171
12172         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12173         {
12174                 // convert the modified arrays to vertex structs
12175                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
12176                 rsurface.batchvertexmeshbuffer = NULL;
12177                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12178                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12179                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12180                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12181                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12182                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12183                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12184                 {
12185                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12186                         {
12187                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12188                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12189                         }
12190                 }
12191                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12192                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12193                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12194                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12195                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12196                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12197                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12198                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12199                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12200         }
12201
12202         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
12203         {
12204                 // convert the modified arrays to vertex structs
12205                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
12206                 rsurface.batchvertexpositionbuffer = NULL;
12207                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
12208                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
12209                 else
12210                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
12211                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
12212         }
12213 }
12214
12215 void RSurf_DrawBatch(void)
12216 {
12217         // sometimes a zero triangle surface (usually a degenerate patch) makes it
12218         // through the pipeline, killing it earlier in the pipeline would have
12219         // per-surface overhead rather than per-batch overhead, so it's best to
12220         // reject it here, before it hits glDraw.
12221         if (rsurface.batchnumtriangles == 0)
12222                 return;
12223 #if 0
12224         // batch debugging code
12225         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
12226         {
12227                 int i;
12228                 int j;
12229                 int c;
12230                 const int *e;
12231                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
12232                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
12233                 {
12234                         c = e[i];
12235                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
12236                         {
12237                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
12238                                 {
12239                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
12240                                                 Sys_Error("RSurf_DrawBatch: index %i uses different texture (%s) than surface %i which it belongs to (which uses %s)\n", c, rsurface.texture->name, j, rsurface.modelsurfaces[j].texture->name);
12241                                         break;
12242                                 }
12243                         }
12244                 }
12245         }
12246 #endif
12247         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);
12248 }
12249
12250 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12251 {
12252         // pick the closest matching water plane
12253         int planeindex, vertexindex, bestplaneindex = -1;
12254         float d, bestd;
12255         vec3_t vert;
12256         const float *v;
12257         r_waterstate_waterplane_t *p;
12258         qboolean prepared = false;
12259         bestd = 0;
12260         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12261         {
12262                 if(p->camera_entity != rsurface.texture->camera_entity)
12263                         continue;
12264                 d = 0;
12265                 if(!prepared)
12266                 {
12267                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
12268                         prepared = true;
12269                         if(rsurface.batchnumvertices == 0)
12270                                 break;
12271                 }
12272                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12273                 {
12274                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
12275                         d += fabs(PlaneDiff(vert, &p->plane));
12276                 }
12277                 if (bestd > d || bestplaneindex < 0)
12278                 {
12279                         bestd = d;
12280                         bestplaneindex = planeindex;
12281                 }
12282         }
12283         return bestplaneindex;
12284         // NOTE: this MAY return a totally unrelated water plane; we can ignore
12285         // this situation though, as it might be better to render single larger
12286         // batches with useless stuff (backface culled for example) than to
12287         // render multiple smaller batches
12288 }
12289
12290 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12291 {
12292         int i;
12293         for (i = 0;i < rsurface.batchnumvertices;i++)
12294                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12295         rsurface.passcolor4f = rsurface.array_passcolor4f;
12296         rsurface.passcolor4f_vertexbuffer = 0;
12297         rsurface.passcolor4f_bufferoffset = 0;
12298 }
12299
12300 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12301 {
12302         int i;
12303         float f;
12304         const float *v;
12305         const float *c;
12306         float *c2;
12307         if (rsurface.passcolor4f)
12308         {
12309                 // generate color arrays
12310                 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)
12311                 {
12312                         f = RSurf_FogVertex(v);
12313                         c2[0] = c[0] * f;
12314                         c2[1] = c[1] * f;
12315                         c2[2] = c[2] * f;
12316                         c2[3] = c[3];
12317                 }
12318         }
12319         else
12320         {
12321                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12322                 {
12323                         f = RSurf_FogVertex(v);
12324                         c2[0] = f;
12325                         c2[1] = f;
12326                         c2[2] = f;
12327                         c2[3] = 1;
12328                 }
12329         }
12330         rsurface.passcolor4f = rsurface.array_passcolor4f;
12331         rsurface.passcolor4f_vertexbuffer = 0;
12332         rsurface.passcolor4f_bufferoffset = 0;
12333 }
12334
12335 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12336 {
12337         int i;
12338         float f;
12339         const float *v;
12340         const float *c;
12341         float *c2;
12342         if (!rsurface.passcolor4f)
12343                 return;
12344         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)
12345         {
12346                 f = RSurf_FogVertex(v);
12347                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12348                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12349                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12350                 c2[3] = c[3];
12351         }
12352         rsurface.passcolor4f = rsurface.array_passcolor4f;
12353         rsurface.passcolor4f_vertexbuffer = 0;
12354         rsurface.passcolor4f_bufferoffset = 0;
12355 }
12356
12357 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12358 {
12359         int i;
12360         const float *c;
12361         float *c2;
12362         if (!rsurface.passcolor4f)
12363                 return;
12364         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12365         {
12366                 c2[0] = c[0] * r;
12367                 c2[1] = c[1] * g;
12368                 c2[2] = c[2] * b;
12369                 c2[3] = c[3] * a;
12370         }
12371         rsurface.passcolor4f = rsurface.array_passcolor4f;
12372         rsurface.passcolor4f_vertexbuffer = 0;
12373         rsurface.passcolor4f_bufferoffset = 0;
12374 }
12375
12376 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12377 {
12378         int i;
12379         const float *c;
12380         float *c2;
12381         if (!rsurface.passcolor4f)
12382                 return;
12383         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12384         {
12385                 c2[0] = c[0] + r_refdef.scene.ambient;
12386                 c2[1] = c[1] + r_refdef.scene.ambient;
12387                 c2[2] = c[2] + r_refdef.scene.ambient;
12388                 c2[3] = c[3];
12389         }
12390         rsurface.passcolor4f = rsurface.array_passcolor4f;
12391         rsurface.passcolor4f_vertexbuffer = 0;
12392         rsurface.passcolor4f_bufferoffset = 0;
12393 }
12394
12395 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12396 {
12397         // TODO: optimize
12398         rsurface.passcolor4f = NULL;
12399         rsurface.passcolor4f_vertexbuffer = 0;
12400         rsurface.passcolor4f_bufferoffset = 0;
12401         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12402         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12403         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12404         GL_Color(r, g, b, a);
12405         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12406         RSurf_DrawBatch();
12407 }
12408
12409 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12410 {
12411         // TODO: optimize applyfog && applycolor case
12412         // just apply fog if necessary, and tint the fog color array if necessary
12413         rsurface.passcolor4f = NULL;
12414         rsurface.passcolor4f_vertexbuffer = 0;
12415         rsurface.passcolor4f_bufferoffset = 0;
12416         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12417         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12418         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12419         GL_Color(r, g, b, a);
12420         RSurf_DrawBatch();
12421 }
12422
12423 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12424 {
12425         // TODO: optimize
12426         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12427         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12428         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12429         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12430         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12431         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12432         GL_Color(r, g, b, a);
12433         RSurf_DrawBatch();
12434 }
12435
12436 static void RSurf_DrawBatch_GL11_ClampColor(void)
12437 {
12438         int i;
12439         const float *c1;
12440         float *c2;
12441         if (!rsurface.passcolor4f)
12442                 return;
12443         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12444         {
12445                 c2[0] = bound(0.0f, c1[0], 1.0f);
12446                 c2[1] = bound(0.0f, c1[1], 1.0f);
12447                 c2[2] = bound(0.0f, c1[2], 1.0f);
12448                 c2[3] = bound(0.0f, c1[3], 1.0f);
12449         }
12450 }
12451
12452 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12453 {
12454         int i;
12455         float f;
12456         const float *v;
12457         const float *n;
12458         float *c;
12459         //vec3_t eyedir;
12460
12461         // fake shading
12462         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)
12463         {
12464                 f = -DotProduct(r_refdef.view.forward, n);
12465                 f = max(0, f);
12466                 f = f * 0.85 + 0.15; // work around so stuff won't get black
12467                 f *= r_refdef.lightmapintensity;
12468                 Vector4Set(c, f, f, f, 1);
12469         }
12470
12471         rsurface.passcolor4f = rsurface.array_passcolor4f;
12472         rsurface.passcolor4f_vertexbuffer = 0;
12473         rsurface.passcolor4f_bufferoffset = 0;
12474 }
12475
12476 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12477 {
12478         RSurf_DrawBatch_GL11_ApplyFakeLight();
12479         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12480         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12481         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12482         GL_Color(r, g, b, a);
12483         RSurf_DrawBatch();
12484 }
12485
12486 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12487 {
12488         int i;
12489         float f;
12490         float alpha;
12491         const float *v;
12492         const float *n;
12493         float *c;
12494         vec3_t ambientcolor;
12495         vec3_t diffusecolor;
12496         vec3_t lightdir;
12497         // TODO: optimize
12498         // model lighting
12499         VectorCopy(rsurface.modellight_lightdir, lightdir);
12500         f = 0.5f * r_refdef.lightmapintensity;
12501         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12502         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12503         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12504         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12505         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12506         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12507         alpha = *a;
12508         if (VectorLength2(diffusecolor) > 0)
12509         {
12510                 // q3-style directional shading
12511                 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)
12512                 {
12513                         if ((f = DotProduct(n, lightdir)) > 0)
12514                                 VectorMA(ambientcolor, f, diffusecolor, c);
12515                         else
12516                                 VectorCopy(ambientcolor, c);
12517                         c[3] = alpha;
12518                 }
12519                 *r = 1;
12520                 *g = 1;
12521                 *b = 1;
12522                 *a = 1;
12523                 rsurface.passcolor4f = rsurface.array_passcolor4f;
12524                 rsurface.passcolor4f_vertexbuffer = 0;
12525                 rsurface.passcolor4f_bufferoffset = 0;
12526                 *applycolor = false;
12527         }
12528         else
12529         {
12530                 *r = ambientcolor[0];
12531                 *g = ambientcolor[1];
12532                 *b = ambientcolor[2];
12533                 rsurface.passcolor4f = NULL;
12534                 rsurface.passcolor4f_vertexbuffer = 0;
12535                 rsurface.passcolor4f_bufferoffset = 0;
12536         }
12537 }
12538
12539 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12540 {
12541         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12542         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12543         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12544         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12545         GL_Color(r, g, b, a);
12546         RSurf_DrawBatch();
12547 }
12548
12549 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12550 {
12551         int i;
12552         float f;
12553         const float *v;
12554         float *c;
12555         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12556         {
12557                 f = 1 - RSurf_FogVertex(v);
12558                 c[0] = r;
12559                 c[1] = g;
12560                 c[2] = b;
12561                 c[3] = f * a;
12562         }
12563 }
12564
12565 void RSurf_SetupDepthAndCulling(void)
12566 {
12567         // submodels are biased to avoid z-fighting with world surfaces that they
12568         // may be exactly overlapping (avoids z-fighting artifacts on certain
12569         // doors and things in Quake maps)
12570         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12571         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12572         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12573         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12574 }
12575
12576 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12577 {
12578         // transparent sky would be ridiculous
12579         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12580                 return;
12581         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12582         skyrenderlater = true;
12583         RSurf_SetupDepthAndCulling();
12584         GL_DepthMask(true);
12585         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12586         // skymasking on them, and Quake3 never did sky masking (unlike
12587         // software Quake and software Quake2), so disable the sky masking
12588         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12589         // and skymasking also looks very bad when noclipping outside the
12590         // level, so don't use it then either.
12591         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12592         {
12593                 R_Mesh_ResetTextureState();
12594                 if (skyrendermasked)
12595                 {
12596                         R_SetupShader_DepthOrShadow();
12597                         // depth-only (masking)
12598                         GL_ColorMask(0,0,0,0);
12599                         // just to make sure that braindead drivers don't draw
12600                         // anything despite that colormask...
12601                         GL_BlendFunc(GL_ZERO, GL_ONE);
12602                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12603                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12604                 }
12605                 else
12606                 {
12607                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12608                         // fog sky
12609                         GL_BlendFunc(GL_ONE, GL_ZERO);
12610                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12611                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12612                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12613                 }
12614                 RSurf_DrawBatch();
12615                 if (skyrendermasked)
12616                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12617         }
12618         R_Mesh_ResetTextureState();
12619         GL_Color(1, 1, 1, 1);
12620 }
12621
12622 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12623 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12624 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12625 {
12626         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12627                 return;
12628         if (prepass)
12629         {
12630                 // render screenspace normalmap to texture
12631                 GL_DepthMask(true);
12632                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12633                 RSurf_DrawBatch();
12634                 return;
12635         }
12636
12637         // bind lightmap texture
12638
12639         // water/refraction/reflection/camera surfaces have to be handled specially
12640         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12641         {
12642                 int start, end, startplaneindex;
12643                 for (start = 0;start < texturenumsurfaces;start = end)
12644                 {
12645                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12646                         if(startplaneindex < 0)
12647                         {
12648                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12649                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12650                                 end = start + 1;
12651                                 continue;
12652                         }
12653                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12654                                 ;
12655                         // now that we have a batch using the same planeindex, render it
12656                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12657                         {
12658                                 // render water or distortion background
12659                                 GL_DepthMask(true);
12660                                 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));
12661                                 RSurf_DrawBatch();
12662                                 // blend surface on top
12663                                 GL_DepthMask(false);
12664                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12665                                 RSurf_DrawBatch();
12666                         }
12667                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12668                         {
12669                                 // render surface with reflection texture as input
12670                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12671                                 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));
12672                                 RSurf_DrawBatch();
12673                         }
12674                 }
12675                 return;
12676         }
12677
12678         // render surface batch normally
12679         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12680         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12681         RSurf_DrawBatch();
12682 }
12683
12684 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12685 {
12686         // OpenGL 1.3 path - anything not completely ancient
12687         qboolean applycolor;
12688         qboolean applyfog;
12689         int layerindex;
12690         const texturelayer_t *layer;
12691         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);
12692         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12693
12694         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12695         {
12696                 vec4_t layercolor;
12697                 int layertexrgbscale;
12698                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12699                 {
12700                         if (layerindex == 0)
12701                                 GL_AlphaTest(true);
12702                         else
12703                         {
12704                                 GL_AlphaTest(false);
12705                                 GL_DepthFunc(GL_EQUAL);
12706                         }
12707                 }
12708                 GL_DepthMask(layer->depthmask && writedepth);
12709                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12710                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12711                 {
12712                         layertexrgbscale = 4;
12713                         VectorScale(layer->color, 0.25f, layercolor);
12714                 }
12715                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12716                 {
12717                         layertexrgbscale = 2;
12718                         VectorScale(layer->color, 0.5f, layercolor);
12719                 }
12720                 else
12721                 {
12722                         layertexrgbscale = 1;
12723                         VectorScale(layer->color, 1.0f, layercolor);
12724                 }
12725                 layercolor[3] = layer->color[3];
12726                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12727                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12728                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12729                 switch (layer->type)
12730                 {
12731                 case TEXTURELAYERTYPE_LITTEXTURE:
12732                         // single-pass lightmapped texture with 2x rgbscale
12733                         R_Mesh_TexBind(0, r_texture_white);
12734                         R_Mesh_TexMatrix(0, NULL);
12735                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12736                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12737                         R_Mesh_TexBind(1, layer->texture);
12738                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12739                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12740                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12741                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12742                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12743                         else if (FAKELIGHT_ENABLED)
12744                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12745                         else if (rsurface.uselightmaptexture)
12746                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12747                         else
12748                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12749                         break;
12750                 case TEXTURELAYERTYPE_TEXTURE:
12751                         // singletexture unlit texture with transparency support
12752                         R_Mesh_TexBind(0, layer->texture);
12753                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12754                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12755                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12756                         R_Mesh_TexBind(1, 0);
12757                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12758                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12759                         break;
12760                 case TEXTURELAYERTYPE_FOG:
12761                         // singletexture fogging
12762                         if (layer->texture)
12763                         {
12764                                 R_Mesh_TexBind(0, layer->texture);
12765                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12766                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12767                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12768                         }
12769                         else
12770                         {
12771                                 R_Mesh_TexBind(0, 0);
12772                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12773                         }
12774                         R_Mesh_TexBind(1, 0);
12775                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12776                         // generate a color array for the fog pass
12777                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12778                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12779                         RSurf_DrawBatch();
12780                         break;
12781                 default:
12782                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12783                 }
12784         }
12785         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12786         {
12787                 GL_DepthFunc(GL_LEQUAL);
12788                 GL_AlphaTest(false);
12789         }
12790 }
12791
12792 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12793 {
12794         // OpenGL 1.1 - crusty old voodoo path
12795         qboolean applyfog;
12796         int layerindex;
12797         const texturelayer_t *layer;
12798         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);
12799         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12800
12801         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12802         {
12803                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12804                 {
12805                         if (layerindex == 0)
12806                                 GL_AlphaTest(true);
12807                         else
12808                         {
12809                                 GL_AlphaTest(false);
12810                                 GL_DepthFunc(GL_EQUAL);
12811                         }
12812                 }
12813                 GL_DepthMask(layer->depthmask && writedepth);
12814                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12815                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12816                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12817                 switch (layer->type)
12818                 {
12819                 case TEXTURELAYERTYPE_LITTEXTURE:
12820                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12821                         {
12822                                 // two-pass lit texture with 2x rgbscale
12823                                 // first the lightmap pass
12824                                 R_Mesh_TexBind(0, r_texture_white);
12825                                 R_Mesh_TexMatrix(0, NULL);
12826                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12827                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12828                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12829                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12830                                 else if (FAKELIGHT_ENABLED)
12831                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12832                                 else if (rsurface.uselightmaptexture)
12833                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12834                                 else
12835                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12836                                 // then apply the texture to it
12837                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12838                                 R_Mesh_TexBind(0, layer->texture);
12839                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12840                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12841                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12842                                 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);
12843                         }
12844                         else
12845                         {
12846                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12847                                 R_Mesh_TexBind(0, layer->texture);
12848                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12849                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12850                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12851                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12852                                         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);
12853                                 else
12854                                         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);
12855                         }
12856                         break;
12857                 case TEXTURELAYERTYPE_TEXTURE:
12858                         // singletexture unlit texture with transparency support
12859                         R_Mesh_TexBind(0, layer->texture);
12860                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12861                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12862                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12863                         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);
12864                         break;
12865                 case TEXTURELAYERTYPE_FOG:
12866                         // singletexture fogging
12867                         if (layer->texture)
12868                         {
12869                                 R_Mesh_TexBind(0, layer->texture);
12870                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12871                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12872                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12873                         }
12874                         else
12875                         {
12876                                 R_Mesh_TexBind(0, 0);
12877                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12878                         }
12879                         // generate a color array for the fog pass
12880                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12881                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12882                         RSurf_DrawBatch();
12883                         break;
12884                 default:
12885                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12886                 }
12887         }
12888         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12889         {
12890                 GL_DepthFunc(GL_LEQUAL);
12891                 GL_AlphaTest(false);
12892         }
12893 }
12894
12895 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12896 {
12897         int vi;
12898         int j;
12899         r_vertexgeneric_t *batchvertex;
12900         float c[4];
12901
12902         GL_AlphaTest(false);
12903 //      R_Mesh_ResetTextureState();
12904         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12905
12906         if(rsurface.texture && rsurface.texture->currentskinframe)
12907         {
12908                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12909                 c[3] *= rsurface.texture->currentalpha;
12910         }
12911         else
12912         {
12913                 c[0] = 1;
12914                 c[1] = 0;
12915                 c[2] = 1;
12916                 c[3] = 1;
12917         }
12918
12919         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12920         {
12921                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12922                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12923                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12924         }
12925
12926         // brighten it up (as texture value 127 means "unlit")
12927         c[0] *= 2 * r_refdef.view.colorscale;
12928         c[1] *= 2 * r_refdef.view.colorscale;
12929         c[2] *= 2 * r_refdef.view.colorscale;
12930
12931         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12932                 c[3] *= r_wateralpha.value;
12933
12934         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12935         {
12936                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12937                 GL_DepthMask(false);
12938         }
12939         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12940         {
12941                 GL_BlendFunc(GL_ONE, GL_ONE);
12942                 GL_DepthMask(false);
12943         }
12944         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12945         {
12946                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12947                 GL_DepthMask(false);
12948         }
12949         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12950         {
12951                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12952                 GL_DepthMask(false);
12953         }
12954         else
12955         {
12956                 GL_BlendFunc(GL_ONE, GL_ZERO);
12957                 GL_DepthMask(writedepth);
12958         }
12959
12960         if (r_showsurfaces.integer == 3)
12961         {
12962                 rsurface.passcolor4f = NULL;
12963
12964                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12965                 {
12966                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12967
12968                         rsurface.passcolor4f = NULL;
12969                         rsurface.passcolor4f_vertexbuffer = 0;
12970                         rsurface.passcolor4f_bufferoffset = 0;
12971                 }
12972                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12973                 {
12974                         qboolean applycolor = true;
12975                         float one = 1.0;
12976
12977                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12978
12979                         r_refdef.lightmapintensity = 1;
12980                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12981                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12982                 }
12983                 else if (FAKELIGHT_ENABLED)
12984                 {
12985                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12986
12987                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
12988                         RSurf_DrawBatch_GL11_ApplyFakeLight();
12989                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12990                 }
12991                 else
12992                 {
12993                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12994
12995                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12996                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12997                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12998                 }
12999
13000                 if(!rsurface.passcolor4f)
13001                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
13002
13003                 RSurf_DrawBatch_GL11_ApplyAmbient();
13004                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
13005                 if(r_refdef.fogenabled)
13006                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
13007                 RSurf_DrawBatch_GL11_ClampColor();
13008
13009                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
13010                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13011                 RSurf_DrawBatch();
13012         }
13013         else if (!r_refdef.view.showdebug)
13014         {
13015                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13016                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13017                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13018                 {
13019                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13020                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
13021                 }
13022                 R_Mesh_PrepareVertices_Generic_Unlock();
13023                 RSurf_DrawBatch();
13024         }
13025         else if (r_showsurfaces.integer == 4)
13026         {
13027                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13028                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13029                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13030                 {
13031                         unsigned char c = vi << 3;
13032                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13033                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
13034                 }
13035                 R_Mesh_PrepareVertices_Generic_Unlock();
13036                 RSurf_DrawBatch();
13037         }
13038         else if (r_showsurfaces.integer == 2)
13039         {
13040                 const int *e;
13041                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13042                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
13043                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
13044                 {
13045                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
13046                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
13047                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
13048                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
13049                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
13050                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
13051                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
13052                 }
13053                 R_Mesh_PrepareVertices_Generic_Unlock();
13054                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
13055         }
13056         else
13057         {
13058                 int texturesurfaceindex;
13059                 int k;
13060                 const msurface_t *surface;
13061                 unsigned char surfacecolor4ub[4];
13062                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13063                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
13064                 vi = 0;
13065                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
13066                 {
13067                         surface = texturesurfacelist[texturesurfaceindex];
13068                         k = (int)(((size_t)surface) / sizeof(msurface_t));
13069                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
13070                         for (j = 0;j < surface->num_vertices;j++)
13071                         {
13072                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13073                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
13074                                 vi++;
13075                         }
13076                 }
13077                 R_Mesh_PrepareVertices_Generic_Unlock();
13078                 RSurf_DrawBatch();
13079         }
13080 }
13081
13082 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13083 {
13084         CHECKGLERROR
13085         RSurf_SetupDepthAndCulling();
13086         if (r_showsurfaces.integer)
13087         {
13088                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13089                 return;
13090         }
13091         switch (vid.renderpath)
13092         {
13093         case RENDERPATH_GL20:
13094         case RENDERPATH_CGGL:
13095         case RENDERPATH_D3D9:
13096         case RENDERPATH_D3D10:
13097         case RENDERPATH_D3D11:
13098                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13099                 break;
13100         case RENDERPATH_GL13:
13101                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13102                 break;
13103         case RENDERPATH_GL11:
13104                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13105                 break;
13106         }
13107         CHECKGLERROR
13108 }
13109
13110 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13111 {
13112         CHECKGLERROR
13113         RSurf_SetupDepthAndCulling();
13114         if (r_showsurfaces.integer)
13115         {
13116                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13117                 return;
13118         }
13119         switch (vid.renderpath)
13120         {
13121         case RENDERPATH_GL20:
13122         case RENDERPATH_CGGL:
13123         case RENDERPATH_D3D9:
13124         case RENDERPATH_D3D10:
13125         case RENDERPATH_D3D11:
13126                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13127                 break;
13128         case RENDERPATH_GL13:
13129                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13130                 break;
13131         case RENDERPATH_GL11:
13132                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13133                 break;
13134         }
13135         CHECKGLERROR
13136 }
13137
13138 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13139 {
13140         int i, j;
13141         int texturenumsurfaces, endsurface;
13142         texture_t *texture;
13143         const msurface_t *surface;
13144 #define MAXBATCH_TRANSPARENTSURFACES 256
13145         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13146
13147         // if the model is static it doesn't matter what value we give for
13148         // wantnormals and wanttangents, so this logic uses only rules applicable
13149         // to a model, knowing that they are meaningless otherwise
13150         if (ent == r_refdef.scene.worldentity)
13151                 RSurf_ActiveWorldEntity();
13152         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13153                 RSurf_ActiveModelEntity(ent, false, false, false);
13154         else
13155         {
13156                 switch (vid.renderpath)
13157                 {
13158                 case RENDERPATH_GL20:
13159                 case RENDERPATH_CGGL:
13160                 case RENDERPATH_D3D9:
13161                 case RENDERPATH_D3D10:
13162                 case RENDERPATH_D3D11:
13163                         RSurf_ActiveModelEntity(ent, true, true, false);
13164                         break;
13165                 case RENDERPATH_GL13:
13166                 case RENDERPATH_GL11:
13167                         RSurf_ActiveModelEntity(ent, true, false, false);
13168                         break;
13169                 }
13170         }
13171
13172         if (r_transparentdepthmasking.integer)
13173         {
13174                 qboolean setup = false;
13175                 for (i = 0;i < numsurfaces;i = j)
13176                 {
13177                         j = i + 1;
13178                         surface = rsurface.modelsurfaces + surfacelist[i];
13179                         texture = surface->texture;
13180                         rsurface.texture = R_GetCurrentTexture(texture);
13181                         rsurface.lightmaptexture = NULL;
13182                         rsurface.deluxemaptexture = NULL;
13183                         rsurface.uselightmaptexture = false;
13184                         // scan ahead until we find a different texture
13185                         endsurface = min(i + 1024, numsurfaces);
13186                         texturenumsurfaces = 0;
13187                         texturesurfacelist[texturenumsurfaces++] = surface;
13188                         for (;j < endsurface;j++)
13189                         {
13190                                 surface = rsurface.modelsurfaces + surfacelist[j];
13191                                 if (texture != surface->texture)
13192                                         break;
13193                                 texturesurfacelist[texturenumsurfaces++] = surface;
13194                         }
13195                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13196                                 continue;
13197                         // render the range of surfaces as depth
13198                         if (!setup)
13199                         {
13200                                 setup = true;
13201                                 GL_ColorMask(0,0,0,0);
13202                                 GL_Color(1,1,1,1);
13203                                 GL_DepthTest(true);
13204                                 GL_BlendFunc(GL_ONE, GL_ZERO);
13205                                 GL_DepthMask(true);
13206                                 GL_AlphaTest(false);
13207 //                              R_Mesh_ResetTextureState();
13208                                 R_SetupShader_DepthOrShadow();
13209                         }
13210                         RSurf_SetupDepthAndCulling();
13211                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13212                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13213                         RSurf_DrawBatch();
13214                 }
13215                 if (setup)
13216                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13217         }
13218
13219         for (i = 0;i < numsurfaces;i = j)
13220         {
13221                 j = i + 1;
13222                 surface = rsurface.modelsurfaces + surfacelist[i];
13223                 texture = surface->texture;
13224                 rsurface.texture = R_GetCurrentTexture(texture);
13225                 // scan ahead until we find a different texture
13226                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13227                 texturenumsurfaces = 0;
13228                 texturesurfacelist[texturenumsurfaces++] = surface;
13229                 if(FAKELIGHT_ENABLED)
13230                 {
13231                         rsurface.lightmaptexture = NULL;
13232                         rsurface.deluxemaptexture = NULL;
13233                         rsurface.uselightmaptexture = false;
13234                         for (;j < endsurface;j++)
13235                         {
13236                                 surface = rsurface.modelsurfaces + surfacelist[j];
13237                                 if (texture != surface->texture)
13238                                         break;
13239                                 texturesurfacelist[texturenumsurfaces++] = surface;
13240                         }
13241                 }
13242                 else
13243                 {
13244                         rsurface.lightmaptexture = surface->lightmaptexture;
13245                         rsurface.deluxemaptexture = surface->deluxemaptexture;
13246                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13247                         for (;j < endsurface;j++)
13248                         {
13249                                 surface = rsurface.modelsurfaces + surfacelist[j];
13250                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13251                                         break;
13252                                 texturesurfacelist[texturenumsurfaces++] = surface;
13253                         }
13254                 }
13255                 // render the range of surfaces
13256                 if (ent == r_refdef.scene.worldentity)
13257                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13258                 else
13259                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13260         }
13261         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13262         GL_AlphaTest(false);
13263 }
13264
13265 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13266 {
13267         // transparent surfaces get pushed off into the transparent queue
13268         int surfacelistindex;
13269         const msurface_t *surface;
13270         vec3_t tempcenter, center;
13271         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13272         {
13273                 surface = texturesurfacelist[surfacelistindex];
13274                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13275                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13276                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13277                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13278                 if (queueentity->transparent_offset) // transparent offset
13279                 {
13280                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13281                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13282                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13283                 }
13284                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13285         }
13286 }
13287
13288 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13289 {
13290         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13291                 return;
13292         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13293                 return;
13294         RSurf_SetupDepthAndCulling();
13295         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13296         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13297         RSurf_DrawBatch();
13298 }
13299
13300 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13301 {
13302         const entity_render_t *queueentity = r_refdef.scene.worldentity;
13303         CHECKGLERROR
13304         if (depthonly)
13305                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13306         else if (prepass)
13307         {
13308                 if (!rsurface.texture->currentnumlayers)
13309                         return;
13310                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13311                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13312                 else
13313                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13314         }
13315         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13316                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13317         else if (!rsurface.texture->currentnumlayers)
13318                 return;
13319         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13320         {
13321                 // in the deferred case, transparent surfaces were queued during prepass
13322                 if (!r_shadow_usingdeferredprepass)
13323                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13324         }
13325         else
13326         {
13327                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13328                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13329         }
13330         CHECKGLERROR
13331 }
13332
13333 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13334 {
13335         int i, j;
13336         texture_t *texture;
13337         // break the surface list down into batches by texture and use of lightmapping
13338         for (i = 0;i < numsurfaces;i = j)
13339         {
13340                 j = i + 1;
13341                 // texture is the base texture pointer, rsurface.texture is the
13342                 // current frame/skin the texture is directing us to use (for example
13343                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13344                 // use skin 1 instead)
13345                 texture = surfacelist[i]->texture;
13346                 rsurface.texture = R_GetCurrentTexture(texture);
13347                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13348                 {
13349                         // if this texture is not the kind we want, skip ahead to the next one
13350                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13351                                 ;
13352                         continue;
13353                 }
13354                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13355                 {
13356                         rsurface.lightmaptexture = NULL;
13357                         rsurface.deluxemaptexture = NULL;
13358                         rsurface.uselightmaptexture = false;
13359                         // simply scan ahead until we find a different texture or lightmap state
13360                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13361                                 ;
13362                 }
13363                 else
13364                 {
13365                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13366                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13367                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13368                         // simply scan ahead until we find a different texture or lightmap state
13369                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13370                                 ;
13371                 }
13372                 // render the range of surfaces
13373                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13374         }
13375 }
13376
13377 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13378 {
13379         CHECKGLERROR
13380         if (depthonly)
13381                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13382         else if (prepass)
13383         {
13384                 if (!rsurface.texture->currentnumlayers)
13385                         return;
13386                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13387                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13388                 else
13389                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13390         }
13391         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13392                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13393         else if (!rsurface.texture->currentnumlayers)
13394                 return;
13395         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13396         {
13397                 // in the deferred case, transparent surfaces were queued during prepass
13398                 if (!r_shadow_usingdeferredprepass)
13399                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13400         }
13401         else
13402         {
13403                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13404                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13405         }
13406         CHECKGLERROR
13407 }
13408
13409 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13410 {
13411         int i, j;
13412         texture_t *texture;
13413         // break the surface list down into batches by texture and use of lightmapping
13414         for (i = 0;i < numsurfaces;i = j)
13415         {
13416                 j = i + 1;
13417                 // texture is the base texture pointer, rsurface.texture is the
13418                 // current frame/skin the texture is directing us to use (for example
13419                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13420                 // use skin 1 instead)
13421                 texture = surfacelist[i]->texture;
13422                 rsurface.texture = R_GetCurrentTexture(texture);
13423                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13424                 {
13425                         // if this texture is not the kind we want, skip ahead to the next one
13426                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13427                                 ;
13428                         continue;
13429                 }
13430                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13431                 {
13432                         rsurface.lightmaptexture = NULL;
13433                         rsurface.deluxemaptexture = NULL;
13434                         rsurface.uselightmaptexture = false;
13435                         // simply scan ahead until we find a different texture or lightmap state
13436                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13437                                 ;
13438                 }
13439                 else
13440                 {
13441                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13442                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13443                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13444                         // simply scan ahead until we find a different texture or lightmap state
13445                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13446                                 ;
13447                 }
13448                 // render the range of surfaces
13449                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13450         }
13451 }
13452
13453 float locboxvertex3f[6*4*3] =
13454 {
13455         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13456         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13457         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13458         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13459         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13460         1,0,0, 0,0,0, 0,1,0, 1,1,0
13461 };
13462
13463 unsigned short locboxelements[6*2*3] =
13464 {
13465          0, 1, 2, 0, 2, 3,
13466          4, 5, 6, 4, 6, 7,
13467          8, 9,10, 8,10,11,
13468         12,13,14, 12,14,15,
13469         16,17,18, 16,18,19,
13470         20,21,22, 20,22,23
13471 };
13472
13473 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13474 {
13475         int i, j;
13476         cl_locnode_t *loc = (cl_locnode_t *)ent;
13477         vec3_t mins, size;
13478         float vertex3f[6*4*3];
13479         CHECKGLERROR
13480         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13481         GL_DepthMask(false);
13482         GL_DepthRange(0, 1);
13483         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13484         GL_DepthTest(true);
13485         GL_CullFace(GL_NONE);
13486         R_EntityMatrix(&identitymatrix);
13487
13488 //      R_Mesh_ResetTextureState();
13489
13490         i = surfacelist[0];
13491         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13492                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13493                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13494                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13495
13496         if (VectorCompare(loc->mins, loc->maxs))
13497         {
13498                 VectorSet(size, 2, 2, 2);
13499                 VectorMA(loc->mins, -0.5f, size, mins);
13500         }
13501         else
13502         {
13503                 VectorCopy(loc->mins, mins);
13504                 VectorSubtract(loc->maxs, loc->mins, size);
13505         }
13506
13507         for (i = 0;i < 6*4*3;)
13508                 for (j = 0;j < 3;j++, i++)
13509                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13510
13511         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13512         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13513         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13514 }
13515
13516 void R_DrawLocs(void)
13517 {
13518         int index;
13519         cl_locnode_t *loc, *nearestloc;
13520         vec3_t center;
13521         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13522         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13523         {
13524                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13525                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13526         }
13527 }
13528
13529 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13530 {
13531         if (decalsystem->decals)
13532                 Mem_Free(decalsystem->decals);
13533         memset(decalsystem, 0, sizeof(*decalsystem));
13534 }
13535
13536 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)
13537 {
13538         tridecal_t *decal;
13539         tridecal_t *decals;
13540         int i;
13541
13542         // expand or initialize the system
13543         if (decalsystem->maxdecals <= decalsystem->numdecals)
13544         {
13545                 decalsystem_t old = *decalsystem;
13546                 qboolean useshortelements;
13547                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13548                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13549                 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)));
13550                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13551                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13552                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13553                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13554                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13555                 if (decalsystem->numdecals)
13556                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13557                 if (old.decals)
13558                         Mem_Free(old.decals);
13559                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13560                         decalsystem->element3i[i] = i;
13561                 if (useshortelements)
13562                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13563                                 decalsystem->element3s[i] = i;
13564         }
13565
13566         // grab a decal and search for another free slot for the next one
13567         decals = decalsystem->decals;
13568         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13569         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13570                 ;
13571         decalsystem->freedecal = i;
13572         if (decalsystem->numdecals <= i)
13573                 decalsystem->numdecals = i + 1;
13574
13575         // initialize the decal
13576         decal->lived = 0;
13577         decal->triangleindex = triangleindex;
13578         decal->surfaceindex = surfaceindex;
13579         decal->decalsequence = decalsequence;
13580         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13581         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13582         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13583         decal->color4ub[0][3] = 255;
13584         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13585         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13586         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13587         decal->color4ub[1][3] = 255;
13588         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13589         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13590         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13591         decal->color4ub[2][3] = 255;
13592         decal->vertex3f[0][0] = v0[0];
13593         decal->vertex3f[0][1] = v0[1];
13594         decal->vertex3f[0][2] = v0[2];
13595         decal->vertex3f[1][0] = v1[0];
13596         decal->vertex3f[1][1] = v1[1];
13597         decal->vertex3f[1][2] = v1[2];
13598         decal->vertex3f[2][0] = v2[0];
13599         decal->vertex3f[2][1] = v2[1];
13600         decal->vertex3f[2][2] = v2[2];
13601         decal->texcoord2f[0][0] = t0[0];
13602         decal->texcoord2f[0][1] = t0[1];
13603         decal->texcoord2f[1][0] = t1[0];
13604         decal->texcoord2f[1][1] = t1[1];
13605         decal->texcoord2f[2][0] = t2[0];
13606         decal->texcoord2f[2][1] = t2[1];
13607 }
13608
13609 extern cvar_t cl_decals_bias;
13610 extern cvar_t cl_decals_models;
13611 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13612 // baseparms, parms, temps
13613 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)
13614 {
13615         int cornerindex;
13616         int index;
13617         float v[9][3];
13618         const float *vertex3f;
13619         int numpoints;
13620         float points[2][9][3];
13621         float temp[3];
13622         float tc[9][2];
13623         float f;
13624         float c[9][4];
13625         const int *e;
13626
13627         e = rsurface.modelelement3i + 3*triangleindex;
13628
13629         vertex3f = rsurface.modelvertex3f;
13630
13631         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13632         {
13633                 index = 3*e[cornerindex];
13634                 VectorCopy(vertex3f + index, v[cornerindex]);
13635         }
13636         // cull backfaces
13637         //TriangleNormal(v[0], v[1], v[2], normal);
13638         //if (DotProduct(normal, localnormal) < 0.0f)
13639         //      continue;
13640         // clip by each of the box planes formed from the projection matrix
13641         // if anything survives, we emit the decal
13642         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]);
13643         if (numpoints < 3)
13644                 return;
13645         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]);
13646         if (numpoints < 3)
13647                 return;
13648         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]);
13649         if (numpoints < 3)
13650                 return;
13651         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]);
13652         if (numpoints < 3)
13653                 return;
13654         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]);
13655         if (numpoints < 3)
13656                 return;
13657         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]);
13658         if (numpoints < 3)
13659                 return;
13660         // some part of the triangle survived, so we have to accept it...
13661         if (dynamic)
13662         {
13663                 // dynamic always uses the original triangle
13664                 numpoints = 3;
13665                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13666                 {
13667                         index = 3*e[cornerindex];
13668                         VectorCopy(vertex3f + index, v[cornerindex]);
13669                 }
13670         }
13671         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13672         {
13673                 // convert vertex positions to texcoords
13674                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13675                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13676                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13677                 // calculate distance fade from the projection origin
13678                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13679                 f = bound(0.0f, f, 1.0f);
13680                 c[cornerindex][0] = r * f;
13681                 c[cornerindex][1] = g * f;
13682                 c[cornerindex][2] = b * f;
13683                 c[cornerindex][3] = 1.0f;
13684                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13685         }
13686         if (dynamic)
13687                 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);
13688         else
13689                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13690                         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);
13691 }
13692 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)
13693 {
13694         matrix4x4_t projection;
13695         decalsystem_t *decalsystem;
13696         qboolean dynamic;
13697         dp_model_t *model;
13698         const msurface_t *surface;
13699         const msurface_t *surfaces;
13700         const int *surfacelist;
13701         const texture_t *texture;
13702         int numtriangles;
13703         int numsurfacelist;
13704         int surfacelistindex;
13705         int surfaceindex;
13706         int triangleindex;
13707         float localorigin[3];
13708         float localnormal[3];
13709         float localmins[3];
13710         float localmaxs[3];
13711         float localsize;
13712         //float normal[3];
13713         float planes[6][4];
13714         float angles[3];
13715         bih_t *bih;
13716         int bih_triangles_count;
13717         int bih_triangles[256];
13718         int bih_surfaces[256];
13719
13720         decalsystem = &ent->decalsystem;
13721         model = ent->model;
13722         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13723         {
13724                 R_DecalSystem_Reset(&ent->decalsystem);
13725                 return;
13726         }
13727
13728         if (!model->brush.data_leafs && !cl_decals_models.integer)
13729         {
13730                 if (decalsystem->model)
13731                         R_DecalSystem_Reset(decalsystem);
13732                 return;
13733         }
13734
13735         if (decalsystem->model != model)
13736                 R_DecalSystem_Reset(decalsystem);
13737         decalsystem->model = model;
13738
13739         RSurf_ActiveModelEntity(ent, false, false, false);
13740
13741         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13742         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13743         VectorNormalize(localnormal);
13744         localsize = worldsize*rsurface.inversematrixscale;
13745         localmins[0] = localorigin[0] - localsize;
13746         localmins[1] = localorigin[1] - localsize;
13747         localmins[2] = localorigin[2] - localsize;
13748         localmaxs[0] = localorigin[0] + localsize;
13749         localmaxs[1] = localorigin[1] + localsize;
13750         localmaxs[2] = localorigin[2] + localsize;
13751
13752         //VectorCopy(localnormal, planes[4]);
13753         //VectorVectors(planes[4], planes[2], planes[0]);
13754         AnglesFromVectors(angles, localnormal, NULL, false);
13755         AngleVectors(angles, planes[0], planes[2], planes[4]);
13756         VectorNegate(planes[0], planes[1]);
13757         VectorNegate(planes[2], planes[3]);
13758         VectorNegate(planes[4], planes[5]);
13759         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13760         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13761         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13762         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13763         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13764         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13765
13766 #if 1
13767 // works
13768 {
13769         matrix4x4_t forwardprojection;
13770         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13771         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13772 }
13773 #else
13774 // broken
13775 {
13776         float projectionvector[4][3];
13777         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13778         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13779         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13780         projectionvector[0][0] = planes[0][0] * ilocalsize;
13781         projectionvector[0][1] = planes[1][0] * ilocalsize;
13782         projectionvector[0][2] = planes[2][0] * ilocalsize;
13783         projectionvector[1][0] = planes[0][1] * ilocalsize;
13784         projectionvector[1][1] = planes[1][1] * ilocalsize;
13785         projectionvector[1][2] = planes[2][1] * ilocalsize;
13786         projectionvector[2][0] = planes[0][2] * ilocalsize;
13787         projectionvector[2][1] = planes[1][2] * ilocalsize;
13788         projectionvector[2][2] = planes[2][2] * ilocalsize;
13789         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13790         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13791         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13792         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13793 }
13794 #endif
13795
13796         dynamic = model->surfmesh.isanimated;
13797         numsurfacelist = model->nummodelsurfaces;
13798         surfacelist = model->sortedmodelsurfaces;
13799         surfaces = model->data_surfaces;
13800
13801         bih = NULL;
13802         bih_triangles_count = -1;
13803         if(!dynamic)
13804         {
13805                 if(model->render_bih.numleafs)
13806                         bih = &model->render_bih;
13807                 else if(model->collision_bih.numleafs)
13808                         bih = &model->collision_bih;
13809         }
13810         if(bih)
13811                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13812         if(bih_triangles_count == 0)
13813                 return;
13814         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13815                 return;
13816         if(bih_triangles_count > 0)
13817         {
13818                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13819                 {
13820                         surfaceindex = bih_surfaces[triangleindex];
13821                         surface = surfaces + surfaceindex;
13822                         texture = surface->texture;
13823                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13824                                 continue;
13825                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13826                                 continue;
13827                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13828                 }
13829         }
13830         else
13831         {
13832                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13833                 {
13834                         surfaceindex = surfacelist[surfacelistindex];
13835                         surface = surfaces + surfaceindex;
13836                         // check cull box first because it rejects more than any other check
13837                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13838                                 continue;
13839                         // skip transparent surfaces
13840                         texture = surface->texture;
13841                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13842                                 continue;
13843                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13844                                 continue;
13845                         numtriangles = surface->num_triangles;
13846                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13847                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13848                 }
13849         }
13850 }
13851
13852 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13853 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)
13854 {
13855         int renderentityindex;
13856         float worldmins[3];
13857         float worldmaxs[3];
13858         entity_render_t *ent;
13859
13860         if (!cl_decals_newsystem.integer)
13861                 return;
13862
13863         worldmins[0] = worldorigin[0] - worldsize;
13864         worldmins[1] = worldorigin[1] - worldsize;
13865         worldmins[2] = worldorigin[2] - worldsize;
13866         worldmaxs[0] = worldorigin[0] + worldsize;
13867         worldmaxs[1] = worldorigin[1] + worldsize;
13868         worldmaxs[2] = worldorigin[2] + worldsize;
13869
13870         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13871
13872         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13873         {
13874                 ent = r_refdef.scene.entities[renderentityindex];
13875                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13876                         continue;
13877
13878                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13879         }
13880 }
13881
13882 typedef struct r_decalsystem_splatqueue_s
13883 {
13884         vec3_t worldorigin;
13885         vec3_t worldnormal;
13886         float color[4];
13887         float tcrange[4];
13888         float worldsize;
13889         int decalsequence;
13890 }
13891 r_decalsystem_splatqueue_t;
13892
13893 int r_decalsystem_numqueued = 0;
13894 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13895
13896 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)
13897 {
13898         r_decalsystem_splatqueue_t *queue;
13899
13900         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13901                 return;
13902
13903         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13904         VectorCopy(worldorigin, queue->worldorigin);
13905         VectorCopy(worldnormal, queue->worldnormal);
13906         Vector4Set(queue->color, r, g, b, a);
13907         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13908         queue->worldsize = worldsize;
13909         queue->decalsequence = cl.decalsequence++;
13910 }
13911
13912 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13913 {
13914         int i;
13915         r_decalsystem_splatqueue_t *queue;
13916
13917         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13918                 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);
13919         r_decalsystem_numqueued = 0;
13920 }
13921
13922 extern cvar_t cl_decals_max;
13923 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13924 {
13925         int i;
13926         decalsystem_t *decalsystem = &ent->decalsystem;
13927         int numdecals;
13928         int killsequence;
13929         tridecal_t *decal;
13930         float frametime;
13931         float lifetime;
13932
13933         if (!decalsystem->numdecals)
13934                 return;
13935
13936         if (r_showsurfaces.integer)
13937                 return;
13938
13939         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13940         {
13941                 R_DecalSystem_Reset(decalsystem);
13942                 return;
13943         }
13944
13945         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13946         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13947
13948         if (decalsystem->lastupdatetime)
13949                 frametime = (cl.time - decalsystem->lastupdatetime);
13950         else
13951                 frametime = 0;
13952         decalsystem->lastupdatetime = cl.time;
13953         decal = decalsystem->decals;
13954         numdecals = decalsystem->numdecals;
13955
13956         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13957         {
13958                 if (decal->color4ub[0][3])
13959                 {
13960                         decal->lived += frametime;
13961                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13962                         {
13963                                 memset(decal, 0, sizeof(*decal));
13964                                 if (decalsystem->freedecal > i)
13965                                         decalsystem->freedecal = i;
13966                         }
13967                 }
13968         }
13969         decal = decalsystem->decals;
13970         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13971                 numdecals--;
13972
13973         // collapse the array by shuffling the tail decals into the gaps
13974         for (;;)
13975         {
13976                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13977                         decalsystem->freedecal++;
13978                 if (decalsystem->freedecal == numdecals)
13979                         break;
13980                 decal[decalsystem->freedecal] = decal[--numdecals];
13981         }
13982
13983         decalsystem->numdecals = numdecals;
13984
13985         if (numdecals <= 0)
13986         {
13987                 // if there are no decals left, reset decalsystem
13988                 R_DecalSystem_Reset(decalsystem);
13989         }
13990 }
13991
13992 extern skinframe_t *decalskinframe;
13993 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13994 {
13995         int i;
13996         decalsystem_t *decalsystem = &ent->decalsystem;
13997         int numdecals;
13998         tridecal_t *decal;
13999         float faderate;
14000         float alpha;
14001         float *v3f;
14002         float *c4f;
14003         float *t2f;
14004         const int *e;
14005         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
14006         int numtris = 0;
14007
14008         numdecals = decalsystem->numdecals;
14009         if (!numdecals)
14010                 return;
14011
14012         if (r_showsurfaces.integer)
14013                 return;
14014
14015         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
14016         {
14017                 R_DecalSystem_Reset(decalsystem);
14018                 return;
14019         }
14020
14021         // if the model is static it doesn't matter what value we give for
14022         // wantnormals and wanttangents, so this logic uses only rules applicable
14023         // to a model, knowing that they are meaningless otherwise
14024         if (ent == r_refdef.scene.worldentity)
14025                 RSurf_ActiveWorldEntity();
14026         else
14027                 RSurf_ActiveModelEntity(ent, false, false, false);
14028
14029         decalsystem->lastupdatetime = cl.time;
14030         decal = decalsystem->decals;
14031
14032         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
14033
14034         // update vertex positions for animated models
14035         v3f = decalsystem->vertex3f;
14036         c4f = decalsystem->color4f;
14037         t2f = decalsystem->texcoord2f;
14038         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14039         {
14040                 if (!decal->color4ub[0][3])
14041                         continue;
14042
14043                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
14044                         continue;
14045
14046                 // update color values for fading decals
14047                 if (decal->lived >= cl_decals_time.value)
14048                 {
14049                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
14050                         alpha *= (1.0f/255.0f);
14051                 }
14052                 else
14053                         alpha = 1.0f/255.0f;
14054
14055                 c4f[ 0] = decal->color4ub[0][0] * alpha;
14056                 c4f[ 1] = decal->color4ub[0][1] * alpha;
14057                 c4f[ 2] = decal->color4ub[0][2] * alpha;
14058                 c4f[ 3] = 1;
14059                 c4f[ 4] = decal->color4ub[1][0] * alpha;
14060                 c4f[ 5] = decal->color4ub[1][1] * alpha;
14061                 c4f[ 6] = decal->color4ub[1][2] * alpha;
14062                 c4f[ 7] = 1;
14063                 c4f[ 8] = decal->color4ub[2][0] * alpha;
14064                 c4f[ 9] = decal->color4ub[2][1] * alpha;
14065                 c4f[10] = decal->color4ub[2][2] * alpha;
14066                 c4f[11] = 1;
14067
14068                 t2f[0] = decal->texcoord2f[0][0];
14069                 t2f[1] = decal->texcoord2f[0][1];
14070                 t2f[2] = decal->texcoord2f[1][0];
14071                 t2f[3] = decal->texcoord2f[1][1];
14072                 t2f[4] = decal->texcoord2f[2][0];
14073                 t2f[5] = decal->texcoord2f[2][1];
14074
14075                 // update vertex positions for animated models
14076                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
14077                 {
14078                         e = rsurface.modelelement3i + 3*decal->triangleindex;
14079                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
14080                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
14081                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
14082                 }
14083                 else
14084                 {
14085                         VectorCopy(decal->vertex3f[0], v3f);
14086                         VectorCopy(decal->vertex3f[1], v3f + 3);
14087                         VectorCopy(decal->vertex3f[2], v3f + 6);
14088                 }
14089
14090                 if (r_refdef.fogenabled)
14091                 {
14092                         alpha = RSurf_FogVertex(v3f);
14093                         VectorScale(c4f, alpha, c4f);
14094                         alpha = RSurf_FogVertex(v3f + 3);
14095                         VectorScale(c4f + 4, alpha, c4f + 4);
14096                         alpha = RSurf_FogVertex(v3f + 6);
14097                         VectorScale(c4f + 8, alpha, c4f + 8);
14098                 }
14099
14100                 v3f += 9;
14101                 c4f += 12;
14102                 t2f += 6;
14103                 numtris++;
14104         }
14105
14106         if (numtris > 0)
14107         {
14108                 r_refdef.stats.drawndecals += numtris;
14109
14110                 // now render the decals all at once
14111                 // (this assumes they all use one particle font texture!)
14112                 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);
14113 //              R_Mesh_ResetTextureState();
14114                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
14115                 GL_DepthMask(false);
14116                 GL_DepthRange(0, 1);
14117                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
14118                 GL_DepthTest(true);
14119                 GL_CullFace(GL_NONE);
14120                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
14121                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
14122                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
14123         }
14124 }
14125
14126 static void R_DrawModelDecals(void)
14127 {
14128         int i, numdecals;
14129
14130         // fade faster when there are too many decals
14131         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14132         for (i = 0;i < r_refdef.scene.numentities;i++)
14133                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14134
14135         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
14136         for (i = 0;i < r_refdef.scene.numentities;i++)
14137                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14138                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14139
14140         R_DecalSystem_ApplySplatEntitiesQueue();
14141
14142         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14143         for (i = 0;i < r_refdef.scene.numentities;i++)
14144                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14145
14146         r_refdef.stats.totaldecals += numdecals;
14147
14148         if (r_showsurfaces.integer)
14149                 return;
14150
14151         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14152
14153         for (i = 0;i < r_refdef.scene.numentities;i++)
14154         {
14155                 if (!r_refdef.viewcache.entityvisible[i])
14156                         continue;
14157                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14158                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14159         }
14160 }
14161
14162 extern cvar_t mod_collision_bih;
14163 void R_DrawDebugModel(void)
14164 {
14165         entity_render_t *ent = rsurface.entity;
14166         int i, j, k, l, flagsmask;
14167         const msurface_t *surface;
14168         dp_model_t *model = ent->model;
14169         vec3_t v;
14170
14171         switch(vid.renderpath)
14172         {
14173         case RENDERPATH_GL11:
14174         case RENDERPATH_GL13:
14175         case RENDERPATH_GL20:
14176         case RENDERPATH_CGGL:
14177                 break;
14178         case RENDERPATH_D3D9:
14179                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14180                 return;
14181         case RENDERPATH_D3D10:
14182                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14183                 return;
14184         case RENDERPATH_D3D11:
14185                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14186                 return;
14187         }
14188
14189         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14190
14191 //      R_Mesh_ResetTextureState();
14192         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14193         GL_DepthRange(0, 1);
14194         GL_DepthTest(!r_showdisabledepthtest.integer);
14195         GL_DepthMask(false);
14196         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14197
14198         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14199         {
14200                 int triangleindex;
14201                 int bihleafindex;
14202                 qboolean cullbox = ent == r_refdef.scene.worldentity;
14203                 const q3mbrush_t *brush;
14204                 const bih_t *bih = &model->collision_bih;
14205                 const bih_leaf_t *bihleaf;
14206                 float vertex3f[3][3];
14207                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14208                 cullbox = false;
14209                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14210                 {
14211                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14212                                 continue;
14213                         switch (bihleaf->type)
14214                         {
14215                         case BIH_BRUSH:
14216                                 brush = model->brush.data_brushes + bihleaf->itemindex;
14217                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
14218                                 {
14219                                         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);
14220                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14221                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14222                                 }
14223                                 break;
14224                         case BIH_COLLISIONTRIANGLE:
14225                                 triangleindex = bihleaf->itemindex;
14226                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14227                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14228                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14229                                 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);
14230                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14231                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14232                                 break;
14233                         case BIH_RENDERTRIANGLE:
14234                                 triangleindex = bihleaf->itemindex;
14235                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14236                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14237                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14238                                 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);
14239                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14240                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14241                                 break;
14242                         }
14243                 }
14244         }
14245
14246         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14247
14248         if (r_showtris.integer || (r_shownormals.value != 0))
14249         {
14250                 if (r_showdisabledepthtest.integer)
14251                 {
14252                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14253                         GL_DepthMask(false);
14254                 }
14255                 else
14256                 {
14257                         GL_BlendFunc(GL_ONE, GL_ZERO);
14258                         GL_DepthMask(true);
14259                 }
14260                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14261                 {
14262                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14263                                 continue;
14264                         rsurface.texture = R_GetCurrentTexture(surface->texture);
14265                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14266                         {
14267                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14268                                 if (r_showtris.value > 0)
14269                                 {
14270                                         if (!rsurface.texture->currentlayers->depthmask)
14271                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14272                                         else if (ent == r_refdef.scene.worldentity)
14273                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14274                                         else
14275                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14276                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14277                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14278                                         RSurf_DrawBatch();
14279                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14280                                         CHECKGLERROR
14281                                 }
14282                                 if (r_shownormals.value < 0)
14283                                 {
14284                                         qglBegin(GL_LINES);
14285                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14286                                         {
14287                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14288                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14289                                                 qglVertex3f(v[0], v[1], v[2]);
14290                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14291                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14292                                                 qglVertex3f(v[0], v[1], v[2]);
14293                                         }
14294                                         qglEnd();
14295                                         CHECKGLERROR
14296                                 }
14297                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14298                                 {
14299                                         qglBegin(GL_LINES);
14300                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14301                                         {
14302                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14303                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14304                                                 qglVertex3f(v[0], v[1], v[2]);
14305                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14306                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14307                                                 qglVertex3f(v[0], v[1], v[2]);
14308                                         }
14309                                         qglEnd();
14310                                         CHECKGLERROR
14311                                         qglBegin(GL_LINES);
14312                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14313                                         {
14314                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14315                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14316                                                 qglVertex3f(v[0], v[1], v[2]);
14317                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14318                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14319                                                 qglVertex3f(v[0], v[1], v[2]);
14320                                         }
14321                                         qglEnd();
14322                                         CHECKGLERROR
14323                                         qglBegin(GL_LINES);
14324                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14325                                         {
14326                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14327                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14328                                                 qglVertex3f(v[0], v[1], v[2]);
14329                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14330                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14331                                                 qglVertex3f(v[0], v[1], v[2]);
14332                                         }
14333                                         qglEnd();
14334                                         CHECKGLERROR
14335                                 }
14336                         }
14337                 }
14338                 rsurface.texture = NULL;
14339         }
14340 }
14341
14342 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14343 int r_maxsurfacelist = 0;
14344 const msurface_t **r_surfacelist = NULL;
14345 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14346 {
14347         int i, j, endj, flagsmask;
14348         dp_model_t *model = r_refdef.scene.worldmodel;
14349         msurface_t *surfaces;
14350         unsigned char *update;
14351         int numsurfacelist = 0;
14352         if (model == NULL)
14353                 return;
14354
14355         if (r_maxsurfacelist < model->num_surfaces)
14356         {
14357                 r_maxsurfacelist = model->num_surfaces;
14358                 if (r_surfacelist)
14359                         Mem_Free((msurface_t**)r_surfacelist);
14360                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14361         }
14362
14363         RSurf_ActiveWorldEntity();
14364
14365         surfaces = model->data_surfaces;
14366         update = model->brushq1.lightmapupdateflags;
14367
14368         // update light styles on this submodel
14369         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14370         {
14371                 model_brush_lightstyleinfo_t *style;
14372                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14373                 {
14374                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14375                         {
14376                                 int *list = style->surfacelist;
14377                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14378                                 for (j = 0;j < style->numsurfaces;j++)
14379                                         update[list[j]] = true;
14380                         }
14381                 }
14382         }
14383
14384         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14385
14386         if (debug)
14387         {
14388                 R_DrawDebugModel();
14389                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14390                 return;
14391         }
14392
14393         rsurface.lightmaptexture = NULL;
14394         rsurface.deluxemaptexture = NULL;
14395         rsurface.uselightmaptexture = false;
14396         rsurface.texture = NULL;
14397         rsurface.rtlight = NULL;
14398         numsurfacelist = 0;
14399         // add visible surfaces to draw list
14400         for (i = 0;i < model->nummodelsurfaces;i++)
14401         {
14402                 j = model->sortedmodelsurfaces[i];
14403                 if (r_refdef.viewcache.world_surfacevisible[j])
14404                         r_surfacelist[numsurfacelist++] = surfaces + j;
14405         }
14406         // update lightmaps if needed
14407         if (model->brushq1.firstrender)
14408         {
14409                 model->brushq1.firstrender = false;
14410                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14411                         if (update[j])
14412                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14413         }
14414         else if (update)
14415         {
14416                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14417                         if (r_refdef.viewcache.world_surfacevisible[j])
14418                                 if (update[j])
14419                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14420         }
14421         // don't do anything if there were no surfaces
14422         if (!numsurfacelist)
14423         {
14424                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14425                 return;
14426         }
14427         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14428         GL_AlphaTest(false);
14429
14430         // add to stats if desired
14431         if (r_speeds.integer && !skysurfaces && !depthonly)
14432         {
14433                 r_refdef.stats.world_surfaces += numsurfacelist;
14434                 for (j = 0;j < numsurfacelist;j++)
14435                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14436         }
14437
14438         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14439 }
14440
14441 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14442 {
14443         int i, j, endj, flagsmask;
14444         dp_model_t *model = ent->model;
14445         msurface_t *surfaces;
14446         unsigned char *update;
14447         int numsurfacelist = 0;
14448         if (model == NULL)
14449                 return;
14450
14451         if (r_maxsurfacelist < model->num_surfaces)
14452         {
14453                 r_maxsurfacelist = model->num_surfaces;
14454                 if (r_surfacelist)
14455                         Mem_Free((msurface_t **)r_surfacelist);
14456                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14457         }
14458
14459         // if the model is static it doesn't matter what value we give for
14460         // wantnormals and wanttangents, so this logic uses only rules applicable
14461         // to a model, knowing that they are meaningless otherwise
14462         if (ent == r_refdef.scene.worldentity)
14463                 RSurf_ActiveWorldEntity();
14464         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14465                 RSurf_ActiveModelEntity(ent, false, false, false);
14466         else if (prepass)
14467                 RSurf_ActiveModelEntity(ent, true, true, true);
14468         else if (depthonly)
14469         {
14470                 switch (vid.renderpath)
14471                 {
14472                 case RENDERPATH_GL20:
14473                 case RENDERPATH_CGGL:
14474                 case RENDERPATH_D3D9:
14475                 case RENDERPATH_D3D10:
14476                 case RENDERPATH_D3D11:
14477                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14478                         break;
14479                 case RENDERPATH_GL13:
14480                 case RENDERPATH_GL11:
14481                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14482                         break;
14483                 }
14484         }
14485         else
14486         {
14487                 switch (vid.renderpath)
14488                 {
14489                 case RENDERPATH_GL20:
14490                 case RENDERPATH_CGGL:
14491                 case RENDERPATH_D3D9:
14492                 case RENDERPATH_D3D10:
14493                 case RENDERPATH_D3D11:
14494                         RSurf_ActiveModelEntity(ent, true, true, false);
14495                         break;
14496                 case RENDERPATH_GL13:
14497                 case RENDERPATH_GL11:
14498                         RSurf_ActiveModelEntity(ent, true, false, false);
14499                         break;
14500                 }
14501         }
14502
14503         surfaces = model->data_surfaces;
14504         update = model->brushq1.lightmapupdateflags;
14505
14506         // update light styles
14507         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14508         {
14509                 model_brush_lightstyleinfo_t *style;
14510                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14511                 {
14512                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14513                         {
14514                                 int *list = style->surfacelist;
14515                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14516                                 for (j = 0;j < style->numsurfaces;j++)
14517                                         update[list[j]] = true;
14518                         }
14519                 }
14520         }
14521
14522         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14523
14524         if (debug)
14525         {
14526                 R_DrawDebugModel();
14527                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14528                 return;
14529         }
14530
14531         rsurface.lightmaptexture = NULL;
14532         rsurface.deluxemaptexture = NULL;
14533         rsurface.uselightmaptexture = false;
14534         rsurface.texture = NULL;
14535         rsurface.rtlight = NULL;
14536         numsurfacelist = 0;
14537         // add visible surfaces to draw list
14538         for (i = 0;i < model->nummodelsurfaces;i++)
14539                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14540         // don't do anything if there were no surfaces
14541         if (!numsurfacelist)
14542         {
14543                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14544                 return;
14545         }
14546         // update lightmaps if needed
14547         if (update)
14548         {
14549                 int updated = 0;
14550                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14551                 {
14552                         if (update[j])
14553                         {
14554                                 updated++;
14555                                 R_BuildLightMap(ent, surfaces + j);
14556                         }
14557                 }
14558         }
14559         if (update)
14560                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14561                         if (update[j])
14562                                 R_BuildLightMap(ent, surfaces + j);
14563         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14564         GL_AlphaTest(false);
14565
14566         // add to stats if desired
14567         if (r_speeds.integer && !skysurfaces && !depthonly)
14568         {
14569                 r_refdef.stats.entities_surfaces += numsurfacelist;
14570                 for (j = 0;j < numsurfacelist;j++)
14571                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14572         }
14573
14574         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14575 }
14576
14577 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14578 {
14579         static texture_t texture;
14580         static msurface_t surface;
14581         const msurface_t *surfacelist = &surface;
14582
14583         // fake enough texture and surface state to render this geometry
14584
14585         texture.update_lastrenderframe = -1; // regenerate this texture
14586         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14587         texture.currentskinframe = skinframe;
14588         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14589         texture.offsetmapping = OFFSETMAPPING_OFF;
14590         texture.offsetscale = 1;
14591         texture.specularscalemod = 1;
14592         texture.specularpowermod = 1;
14593
14594         surface.texture = &texture;
14595         surface.num_triangles = numtriangles;
14596         surface.num_firsttriangle = firsttriangle;
14597         surface.num_vertices = numvertices;
14598         surface.num_firstvertex = firstvertex;
14599
14600         // now render it
14601         rsurface.texture = R_GetCurrentTexture(surface.texture);
14602         rsurface.lightmaptexture = NULL;
14603         rsurface.deluxemaptexture = NULL;
14604         rsurface.uselightmaptexture = false;
14605         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14606 }
14607
14608 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)
14609 {
14610         static msurface_t surface;
14611         const msurface_t *surfacelist = &surface;
14612
14613         // fake enough texture and surface state to render this geometry
14614         surface.texture = texture;
14615         surface.num_triangles = numtriangles;
14616         surface.num_firsttriangle = firsttriangle;
14617         surface.num_vertices = numvertices;
14618         surface.num_firstvertex = firstvertex;
14619
14620         // now render it
14621         rsurface.texture = R_GetCurrentTexture(surface.texture);
14622         rsurface.lightmaptexture = NULL;
14623         rsurface.deluxemaptexture = NULL;
14624         rsurface.uselightmaptexture = false;
14625         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14626 }