]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
illuminated surfaces are now sorted by texture, giving a good fps
[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 "       gl_FragColor = gl_Color;\n"
813 "#ifdef USEDIFFUSE\n"
814 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
815 "#endif\n"
816 "\n"
817 "#ifdef USESPECULAR\n"
818 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
819 "# ifdef USECOLORMAPPING\n"
820 "       gl_FragColor *= tex2;\n"
821 "# endif\n"
822 "# ifdef USEGLOW\n"
823 "       gl_FragColor += tex2;\n"
824 "# endif\n"
825 "# ifdef USEVERTEXTEXTUREBLEND\n"
826 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
827 "# endif\n"
828 "#endif\n"
829 "}\n"
830 "#endif\n"
831 "#else // !MODE_GENERIC\n"
832 "\n"
833 "\n"
834 "\n"
835 "\n"
836 "#ifdef MODE_BLOOMBLUR\n"
837 "varying TexCoord;\n"
838 "#ifdef VERTEX_SHADER\n"
839 "void main(void)\n"
840 "{\n"
841 "       gl_FrontColor = gl_Color;\n"
842 "       TexCoord = gl_MultiTexCoord0.xy;\n"
843 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
844 "}\n"
845 "#endif\n"
846 "\n"
847 "#ifdef FRAGMENT_SHADER\n"
848 "uniform sampler2D Texture_First;\n"
849 "uniform vec4 BloomBlur_Parameters;\n"
850 "\n"
851 "void main(void)\n"
852 "{\n"
853 "       int i;\n"
854 "       vec2 tc = TexCoord;\n"
855 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
856 "       tc += BloomBlur_Parameters.xy;\n"
857 "       for (i = 1;i < SAMPLES;i++)\n"
858 "       {\n"
859 "               color += texture2D(Texture_First, tc).rgb;\n"
860 "               tc += BloomBlur_Parameters.xy;\n"
861 "       }\n"
862 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
863 "}\n"
864 "#endif\n"
865 "#else // !MODE_BLOOMBLUR\n"
866 "#ifdef MODE_REFRACTION\n"
867 "varying vec2 TexCoord;\n"
868 "varying vec4 ModelViewProjectionPosition;\n"
869 "uniform mat4 TexMatrix;\n"
870 "#ifdef VERTEX_SHADER\n"
871 "\n"
872 "void main(void)\n"
873 "{\n"
874 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
875 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
876 "       ModelViewProjectionPosition = gl_Position;\n"
877 "}\n"
878 "#endif\n"
879 "\n"
880 "#ifdef FRAGMENT_SHADER\n"
881 "uniform sampler2D Texture_Normal;\n"
882 "uniform sampler2D Texture_Refraction;\n"
883 "uniform sampler2D Texture_Reflection;\n"
884 "\n"
885 "uniform vec4 DistortScaleRefractReflect;\n"
886 "uniform vec4 ScreenScaleRefractReflect;\n"
887 "uniform vec4 ScreenCenterRefractReflect;\n"
888 "uniform vec4 RefractColor;\n"
889 "uniform vec4 ReflectColor;\n"
890 "uniform float ReflectFactor;\n"
891 "uniform float ReflectOffset;\n"
892 "\n"
893 "void main(void)\n"
894 "{\n"
895 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
896 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
897 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
898 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
899 "       // FIXME temporary hack to detect the case that the reflection\n"
900 "       // gets blackened at edges due to leaving the area that contains actual\n"
901 "       // content.\n"
902 "       // Remove this 'ack once we have a better way to stop this thing from\n"
903 "       // 'appening.\n"
904 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
905 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
906 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
907 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
908 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
909 "       gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
910 "}\n"
911 "#endif\n"
912 "#else // !MODE_REFRACTION\n"
913 "\n"
914 "\n"
915 "\n"
916 "\n"
917 "#ifdef MODE_WATER\n"
918 "varying vec2 TexCoord;\n"
919 "varying vec3 EyeVector;\n"
920 "varying vec4 ModelViewProjectionPosition;\n"
921 "#ifdef VERTEX_SHADER\n"
922 "uniform vec3 EyePosition;\n"
923 "uniform mat4 TexMatrix;\n"
924 "\n"
925 "void main(void)\n"
926 "{\n"
927 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
928 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
929 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
930 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
931 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
932 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
933 "       ModelViewProjectionPosition = gl_Position;\n"
934 "}\n"
935 "#endif\n"
936 "\n"
937 "#ifdef FRAGMENT_SHADER\n"
938 "uniform sampler2D Texture_Normal;\n"
939 "uniform sampler2D Texture_Refraction;\n"
940 "uniform sampler2D Texture_Reflection;\n"
941 "\n"
942 "uniform vec4 DistortScaleRefractReflect;\n"
943 "uniform vec4 ScreenScaleRefractReflect;\n"
944 "uniform vec4 ScreenCenterRefractReflect;\n"
945 "uniform vec4 RefractColor;\n"
946 "uniform vec4 ReflectColor;\n"
947 "uniform float ReflectFactor;\n"
948 "uniform float ReflectOffset;\n"
949 "uniform float ClientTime;\n"
950 "#ifdef USENORMALMAPSCROLLBLEND\n"
951 "uniform vec2 NormalmapScrollBlend;\n"
952 "#endif\n"
953 "\n"
954 "void main(void)\n"
955 "{\n"
956 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
957 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
958 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
959 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
960 "       // slight water animation via 2 layer scrolling (todo: tweak)\n"
961 "       #ifdef USENORMALMAPSCROLLBLEND\n"
962 "               vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
963 "               normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
964 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
965 "       #else\n"
966 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
967 "       #endif\n"
968 "       // FIXME temporary hack to detect the case that the reflection\n"
969 "       // gets blackened at edges due to leaving the area that contains actual\n"
970 "       // content.\n"
971 "       // Remove this 'ack once we have a better way to stop this thing from\n"
972 "       // 'appening.\n"
973 "       float f1 = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
974 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
975 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
976 "       f1      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
977 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f1);\n"
978 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
979 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
980 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
981 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
982 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
983 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
984 "       gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
985 "       gl_FragColor.a = f1 + 0.5;\n"
986 "}\n"
987 "#endif\n"
988 "#else // !MODE_WATER\n"
989 "\n"
990 "\n"
991 "\n"
992 "\n"
993 "// common definitions between vertex shader and fragment shader:\n"
994 "\n"
995 "varying vec2 TexCoord;\n"
996 "#ifdef USEVERTEXTEXTUREBLEND\n"
997 "varying vec2 TexCoord2;\n"
998 "#endif\n"
999 "#ifdef USELIGHTMAP\n"
1000 "varying vec2 TexCoordLightmap;\n"
1001 "#endif\n"
1002 "\n"
1003 "#ifdef MODE_LIGHTSOURCE\n"
1004 "varying vec3 CubeVector;\n"
1005 "#endif\n"
1006 "\n"
1007 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1008 "varying vec3 LightVector;\n"
1009 "#endif\n"
1010 "\n"
1011 "#ifdef USEEYEVECTOR\n"
1012 "varying vec3 EyeVector;\n"
1013 "#endif\n"
1014 "#ifdef USEFOG\n"
1015 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1016 "#endif\n"
1017 "\n"
1018 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1019 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1020 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1021 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
1022 "#endif\n"
1023 "\n"
1024 "#ifdef USEREFLECTION\n"
1025 "varying vec4 ModelViewProjectionPosition;\n"
1026 "#endif\n"
1027 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1028 "uniform vec3 LightPosition;\n"
1029 "varying vec4 ModelViewPosition;\n"
1030 "#endif\n"
1031 "\n"
1032 "#ifdef MODE_LIGHTSOURCE\n"
1033 "uniform vec3 LightPosition;\n"
1034 "#endif\n"
1035 "uniform vec3 EyePosition;\n"
1036 "#ifdef MODE_LIGHTDIRECTION\n"
1037 "uniform vec3 LightDir;\n"
1038 "#endif\n"
1039 "uniform vec4 FogPlane;\n"
1040 "\n"
1041 "#ifdef USESHADOWMAPORTHO\n"
1042 "varying vec3 ShadowMapTC;\n"
1043 "#endif\n"
1044 "\n"
1045 "\n"
1046 "\n"
1047 "\n"
1048 "\n"
1049 "// 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"
1050 "\n"
1051 "// fragment shader specific:\n"
1052 "#ifdef FRAGMENT_SHADER\n"
1053 "\n"
1054 "uniform sampler2D Texture_Normal;\n"
1055 "uniform sampler2D Texture_Color;\n"
1056 "uniform sampler2D Texture_Gloss;\n"
1057 "#ifdef USEGLOW\n"
1058 "uniform sampler2D Texture_Glow;\n"
1059 "#endif\n"
1060 "#ifdef USEVERTEXTEXTUREBLEND\n"
1061 "uniform sampler2D Texture_SecondaryNormal;\n"
1062 "uniform sampler2D Texture_SecondaryColor;\n"
1063 "uniform sampler2D Texture_SecondaryGloss;\n"
1064 "#ifdef USEGLOW\n"
1065 "uniform sampler2D Texture_SecondaryGlow;\n"
1066 "#endif\n"
1067 "#endif\n"
1068 "#ifdef USECOLORMAPPING\n"
1069 "uniform sampler2D Texture_Pants;\n"
1070 "uniform sampler2D Texture_Shirt;\n"
1071 "#endif\n"
1072 "#ifdef USEFOG\n"
1073 "#ifdef USEFOGHEIGHTTEXTURE\n"
1074 "uniform sampler2D Texture_FogHeightTexture;\n"
1075 "#endif\n"
1076 "uniform sampler2D Texture_FogMask;\n"
1077 "#endif\n"
1078 "#ifdef USELIGHTMAP\n"
1079 "uniform sampler2D Texture_Lightmap;\n"
1080 "#endif\n"
1081 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1082 "uniform sampler2D Texture_Deluxemap;\n"
1083 "#endif\n"
1084 "#ifdef USEREFLECTION\n"
1085 "uniform sampler2D Texture_Reflection;\n"
1086 "#endif\n"
1087 "\n"
1088 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1089 "uniform sampler2D Texture_ScreenDepth;\n"
1090 "uniform sampler2D Texture_ScreenNormalMap;\n"
1091 "#endif\n"
1092 "#ifdef USEDEFERREDLIGHTMAP\n"
1093 "uniform sampler2D Texture_ScreenDiffuse;\n"
1094 "uniform sampler2D Texture_ScreenSpecular;\n"
1095 "#endif\n"
1096 "\n"
1097 "uniform myhalf3 Color_Pants;\n"
1098 "uniform myhalf3 Color_Shirt;\n"
1099 "uniform myhalf3 FogColor;\n"
1100 "\n"
1101 "#ifdef USEFOG\n"
1102 "uniform float FogRangeRecip;\n"
1103 "uniform float FogPlaneViewDist;\n"
1104 "uniform float FogHeightFade;\n"
1105 "vec3 FogVertex(vec3 surfacecolor)\n"
1106 "{\n"
1107 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1108 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1109 "       float fogfrac;\n"
1110 "#ifdef USEFOGHEIGHTTEXTURE\n"
1111 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1112 "       fogfrac = fogheightpixel.a;\n"
1113 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1114 "#else\n"
1115 "# ifdef USEFOGOUTSIDE\n"
1116 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1117 "# else\n"
1118 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1119 "# endif\n"
1120 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1121 "#endif\n"
1122 "}\n"
1123 "#endif\n"
1124 "\n"
1125 "#ifdef USEOFFSETMAPPING\n"
1126 "uniform float OffsetMapping_Scale;\n"
1127 "vec2 OffsetMapping(vec2 TexCoord)\n"
1128 "{\n"
1129 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1130 "       // 14 sample relief mapping: linear search and then binary search\n"
1131 "       // this basically steps forward a small amount repeatedly until it finds\n"
1132 "       // itself inside solid, then jitters forward and back using decreasing\n"
1133 "       // amounts to find the impact\n"
1134 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1135 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1136 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1137 "       vec3 RT = vec3(TexCoord, 1);\n"
1138 "       OffsetVector *= 0.1;\n"
1139 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1140 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1141 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1142 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1143 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1144 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\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)          - 0.5);\n"
1149 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1150 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1151 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1152 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1153 "       return RT.xy;\n"
1154 "#else\n"
1155 "       // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1156 "       // this basically moves forward the full distance, and then backs up based\n"
1157 "       // on height of samples\n"
1158 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1159 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1160 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1161 "       TexCoord += OffsetVector;\n"
1162 "       OffsetVector *= 0.5;\n"
1163 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1164 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1165 "       return TexCoord;\n"
1166 "#endif\n"
1167 "}\n"
1168 "#endif // USEOFFSETMAPPING\n"
1169 "\n"
1170 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1171 "uniform sampler2D Texture_Attenuation;\n"
1172 "uniform samplerCube Texture_Cube;\n"
1173 "#endif\n"
1174 "\n"
1175 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1176 "\n"
1177 "#ifdef USESHADOWMAP2D\n"
1178 "# ifdef USESHADOWSAMPLER\n"
1179 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1180 "# else\n"
1181 "uniform sampler2D Texture_ShadowMap2D;\n"
1182 "# endif\n"
1183 "#endif\n"
1184 "\n"
1185 "#ifdef USESHADOWMAPVSDCT\n"
1186 "uniform samplerCube Texture_CubeProjection;\n"
1187 "#endif\n"
1188 "\n"
1189 "#if defined(USESHADOWMAP2D)\n"
1190 "uniform vec2 ShadowMap_TextureScale;\n"
1191 "uniform vec4 ShadowMap_Parameters;\n"
1192 "#endif\n"
1193 "\n"
1194 "#if defined(USESHADOWMAP2D)\n"
1195 "# ifdef USESHADOWMAPORTHO\n"
1196 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1197 "# else\n"
1198 "#  ifdef USESHADOWMAPVSDCT\n"
1199 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1200 "{\n"
1201 "       vec3 adir = abs(dir);\n"
1202 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1203 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1204 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1205 "}\n"
1206 "#  else\n"
1207 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1208 "{\n"
1209 "       vec3 adir = abs(dir);\n"
1210 "       float ma = adir.z;\n"
1211 "       vec4 proj = vec4(dir, 2.5);\n"
1212 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1213 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1214 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1215 "       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"
1216 "}\n"
1217 "#  endif\n"
1218 "# endif\n"
1219 "#endif // defined(USESHADOWMAP2D)\n"
1220 "\n"
1221 "# ifdef USESHADOWMAP2D\n"
1222 "float ShadowMapCompare(vec3 dir)\n"
1223 "{\n"
1224 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1225 "       float f;\n"
1226 "\n"
1227 "#  ifdef USESHADOWSAMPLER\n"
1228 "#    ifdef USESHADOWMAPPCF\n"
1229 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1230 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1231 "       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"
1232 "#    else\n"
1233 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1234 "#    endif\n"
1235 "#  else\n"
1236 "#    ifdef USESHADOWMAPPCF\n"
1237 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1238 "#      ifdef GL_ARB_texture_gather\n"
1239 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1240 "#      else\n"
1241 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1242 "#      endif\n"
1243 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1244 "#      if USESHADOWMAPPCF > 1\n"
1245 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1246 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1247 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1248 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1249 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1250 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1251 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1252 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1253 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1254 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1255 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1256 "       locols.yz += group2.ab;\n"
1257 "       hicols.yz += group8.rg;\n"
1258 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1259 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1260 "                               mix(locols, hicols, offset.y);\n"
1261 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1262 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1263 "       f = dot(cols, vec4(1.0/25.0));\n"
1264 "#      else\n"
1265 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1266 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1267 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1268 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1269 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1270 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1271 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1272 "#      endif\n"
1273 "#     else\n"
1274 "#      ifdef GL_EXT_gpu_shader4\n"
1275 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1276 "#      else\n"
1277 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1278 "#      endif\n"
1279 "#      if USESHADOWMAPPCF > 1\n"
1280 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1281 "       center *= ShadowMap_TextureScale;\n"
1282 "       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"
1283 "       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"
1284 "       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"
1285 "       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"
1286 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1287 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1288 "#      else\n"
1289 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1290 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1291 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1292 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1293 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1294 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1295 "#      endif\n"
1296 "#     endif\n"
1297 "#    else\n"
1298 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1299 "#    endif\n"
1300 "#  endif\n"
1301 "#  ifdef USESHADOWMAPORTHO\n"
1302 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1303 "#  else\n"
1304 "       return f;\n"
1305 "#  endif\n"
1306 "}\n"
1307 "# endif\n"
1308 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1309 "#endif // FRAGMENT_SHADER\n"
1310 "\n"
1311 "\n"
1312 "\n"
1313 "\n"
1314 "#ifdef MODE_DEFERREDGEOMETRY\n"
1315 "#ifdef VERTEX_SHADER\n"
1316 "uniform mat4 TexMatrix;\n"
1317 "#ifdef USEVERTEXTEXTUREBLEND\n"
1318 "uniform mat4 BackgroundTexMatrix;\n"
1319 "#endif\n"
1320 "uniform mat4 ModelViewMatrix;\n"
1321 "void main(void)\n"
1322 "{\n"
1323 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1324 "#ifdef USEVERTEXTEXTUREBLEND\n"
1325 "       gl_FrontColor = gl_Color;\n"
1326 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1327 "#endif\n"
1328 "\n"
1329 "       // transform unnormalized eye direction into tangent space\n"
1330 "#ifdef USEOFFSETMAPPING\n"
1331 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1332 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1333 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1334 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1335 "#endif\n"
1336 "\n"
1337 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1338 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1339 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1340 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1341 "}\n"
1342 "#endif // VERTEX_SHADER\n"
1343 "\n"
1344 "#ifdef FRAGMENT_SHADER\n"
1345 "void main(void)\n"
1346 "{\n"
1347 "#ifdef USEOFFSETMAPPING\n"
1348 "       // apply offsetmapping\n"
1349 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1350 "#define TexCoord TexCoordOffset\n"
1351 "#endif\n"
1352 "\n"
1353 "#ifdef USEALPHAKILL\n"
1354 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1355 "               discard;\n"
1356 "#endif\n"
1357 "\n"
1358 "#ifdef USEVERTEXTEXTUREBLEND\n"
1359 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1360 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1361 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1362 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1363 "#endif\n"
1364 "\n"
1365 "#ifdef USEVERTEXTEXTUREBLEND\n"
1366 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1367 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1368 "#else\n"
1369 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1370 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1371 "#endif\n"
1372 "\n"
1373 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1374 "}\n"
1375 "#endif // FRAGMENT_SHADER\n"
1376 "#else // !MODE_DEFERREDGEOMETRY\n"
1377 "\n"
1378 "\n"
1379 "\n"
1380 "\n"
1381 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1382 "#ifdef VERTEX_SHADER\n"
1383 "uniform mat4 ModelViewMatrix;\n"
1384 "void main(void)\n"
1385 "{\n"
1386 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1387 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1388 "}\n"
1389 "#endif // VERTEX_SHADER\n"
1390 "\n"
1391 "#ifdef FRAGMENT_SHADER\n"
1392 "uniform mat4 ViewToLight;\n"
1393 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1394 "uniform vec2 ScreenToDepth;\n"
1395 "uniform myhalf3 DeferredColor_Ambient;\n"
1396 "uniform myhalf3 DeferredColor_Diffuse;\n"
1397 "#ifdef USESPECULAR\n"
1398 "uniform myhalf3 DeferredColor_Specular;\n"
1399 "uniform myhalf SpecularPower;\n"
1400 "#endif\n"
1401 "uniform myhalf2 PixelToScreenTexCoord;\n"
1402 "void main(void)\n"
1403 "{\n"
1404 "       // calculate viewspace pixel position\n"
1405 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1406 "       vec3 position;\n"
1407 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1408 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1409 "       // decode viewspace pixel normal\n"
1410 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1411 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1412 "       // surfacenormal = pixel normal in viewspace\n"
1413 "       // LightVector = pixel to light in viewspace\n"
1414 "       // CubeVector = position in lightspace\n"
1415 "       // eyevector = pixel to view in viewspace\n"
1416 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1417 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1418 "#ifdef USEDIFFUSE\n"
1419 "       // calculate diffuse shading\n"
1420 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1421 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1422 "#endif\n"
1423 "#ifdef USESPECULAR\n"
1424 "       // calculate directional shading\n"
1425 "       vec3 eyevector = position * -1.0;\n"
1426 "#  ifdef USEEXACTSPECULARMATH\n"
1427 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1428 "#  else\n"
1429 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1430 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1431 "#  endif\n"
1432 "#endif\n"
1433 "\n"
1434 "#if defined(USESHADOWMAP2D)\n"
1435 "       fade *= ShadowMapCompare(CubeVector);\n"
1436 "#endif\n"
1437 "\n"
1438 "#ifdef USEDIFFUSE\n"
1439 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1440 "#else\n"
1441 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1442 "#endif\n"
1443 "#ifdef USESPECULAR\n"
1444 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1445 "#else\n"
1446 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1447 "#endif\n"
1448 "\n"
1449 "# ifdef USECUBEFILTER\n"
1450 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1451 "       gl_FragData[0].rgb *= cubecolor;\n"
1452 "       gl_FragData[1].rgb *= cubecolor;\n"
1453 "# endif\n"
1454 "}\n"
1455 "#endif // FRAGMENT_SHADER\n"
1456 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1457 "\n"
1458 "\n"
1459 "\n"
1460 "\n"
1461 "#ifdef VERTEX_SHADER\n"
1462 "uniform mat4 TexMatrix;\n"
1463 "#ifdef USEVERTEXTEXTUREBLEND\n"
1464 "uniform mat4 BackgroundTexMatrix;\n"
1465 "#endif\n"
1466 "#ifdef MODE_LIGHTSOURCE\n"
1467 "uniform mat4 ModelToLight;\n"
1468 "#endif\n"
1469 "#ifdef USESHADOWMAPORTHO\n"
1470 "uniform mat4 ShadowMapMatrix;\n"
1471 "#endif\n"
1472 "void main(void)\n"
1473 "{\n"
1474 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1475 "       gl_FrontColor = gl_Color;\n"
1476 "#endif\n"
1477 "       // copy the surface texcoord\n"
1478 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1479 "#ifdef USEVERTEXTEXTUREBLEND\n"
1480 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1481 "#endif\n"
1482 "#ifdef USELIGHTMAP\n"
1483 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1484 "#endif\n"
1485 "\n"
1486 "#ifdef MODE_LIGHTSOURCE\n"
1487 "       // transform vertex position into light attenuation/cubemap space\n"
1488 "       // (-1 to +1 across the light box)\n"
1489 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1490 "\n"
1491 "# ifdef USEDIFFUSE\n"
1492 "       // transform unnormalized light direction into tangent space\n"
1493 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1494 "       //  normalize it per pixel)\n"
1495 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1496 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1497 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1498 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1499 "# endif\n"
1500 "#endif\n"
1501 "\n"
1502 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1503 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1504 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1505 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1506 "#endif\n"
1507 "\n"
1508 "       // transform unnormalized eye direction into tangent space\n"
1509 "#ifdef USEEYEVECTOR\n"
1510 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1511 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1512 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1513 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1514 "#endif\n"
1515 "\n"
1516 "#ifdef USEFOG\n"
1517 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1518 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1519 "#endif\n"
1520 "\n"
1521 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1522 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1523 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1524 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1525 "#endif\n"
1526 "\n"
1527 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1528 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1529 "\n"
1530 "#ifdef USESHADOWMAPORTHO\n"
1531 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1532 "#endif\n"
1533 "\n"
1534 "#ifdef USEREFLECTION\n"
1535 "       ModelViewProjectionPosition = gl_Position;\n"
1536 "#endif\n"
1537 "}\n"
1538 "#endif // VERTEX_SHADER\n"
1539 "\n"
1540 "\n"
1541 "\n"
1542 "\n"
1543 "#ifdef FRAGMENT_SHADER\n"
1544 "#ifdef USEDEFERREDLIGHTMAP\n"
1545 "uniform myhalf2 PixelToScreenTexCoord;\n"
1546 "uniform myhalf3 DeferredMod_Diffuse;\n"
1547 "uniform myhalf3 DeferredMod_Specular;\n"
1548 "#endif\n"
1549 "uniform myhalf3 Color_Ambient;\n"
1550 "uniform myhalf3 Color_Diffuse;\n"
1551 "uniform myhalf3 Color_Specular;\n"
1552 "uniform myhalf SpecularPower;\n"
1553 "#ifdef USEGLOW\n"
1554 "uniform myhalf3 Color_Glow;\n"
1555 "#endif\n"
1556 "uniform myhalf Alpha;\n"
1557 "#ifdef USEREFLECTION\n"
1558 "uniform vec4 DistortScaleRefractReflect;\n"
1559 "uniform vec4 ScreenScaleRefractReflect;\n"
1560 "uniform vec4 ScreenCenterRefractReflect;\n"
1561 "uniform myhalf4 ReflectColor;\n"
1562 "#endif\n"
1563 "#ifdef USEREFLECTCUBE\n"
1564 "uniform mat4 ModelToReflectCube;\n"
1565 "uniform sampler2D Texture_ReflectMask;\n"
1566 "uniform samplerCube Texture_ReflectCube;\n"
1567 "#endif\n"
1568 "#ifdef MODE_LIGHTDIRECTION\n"
1569 "uniform myhalf3 LightColor;\n"
1570 "#endif\n"
1571 "#ifdef MODE_LIGHTSOURCE\n"
1572 "uniform myhalf3 LightColor;\n"
1573 "#endif\n"
1574 "void main(void)\n"
1575 "{\n"
1576 "#ifdef USEOFFSETMAPPING\n"
1577 "       // apply offsetmapping\n"
1578 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1579 "#define TexCoord TexCoordOffset\n"
1580 "#endif\n"
1581 "\n"
1582 "       // combine the diffuse textures (base, pants, shirt)\n"
1583 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1584 "#ifdef USEALPHAKILL\n"
1585 "       if (color.a < 0.5)\n"
1586 "               discard;\n"
1587 "#endif\n"
1588 "       color.a *= Alpha;\n"
1589 "#ifdef USECOLORMAPPING\n"
1590 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1591 "#endif\n"
1592 "#ifdef USEVERTEXTEXTUREBLEND\n"
1593 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1594 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1595 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1596 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1597 "       color.a = 1.0;\n"
1598 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1599 "#endif\n"
1600 "\n"
1601 "       // get the surface normal\n"
1602 "#ifdef USEVERTEXTEXTUREBLEND\n"
1603 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1604 "#else\n"
1605 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1606 "#endif\n"
1607 "\n"
1608 "       // get the material colors\n"
1609 "       myhalf3 diffusetex = color.rgb;\n"
1610 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1611 "# ifdef USEVERTEXTEXTUREBLEND\n"
1612 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1613 "# else\n"
1614 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1615 "# endif\n"
1616 "#endif\n"
1617 "\n"
1618 "#ifdef USEREFLECTCUBE\n"
1619 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1620 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1621 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1622 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1623 "#endif\n"
1624 "\n"
1625 "\n"
1626 "\n"
1627 "\n"
1628 "#ifdef MODE_LIGHTSOURCE\n"
1629 "       // light source\n"
1630 "#ifdef USEDIFFUSE\n"
1631 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1632 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1633 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1634 "#ifdef USESPECULAR\n"
1635 "#ifdef USEEXACTSPECULARMATH\n"
1636 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1637 "#else\n"
1638 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1639 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1640 "#endif\n"
1641 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1642 "#endif\n"
1643 "#else\n"
1644 "       color.rgb = diffusetex * Color_Ambient;\n"
1645 "#endif\n"
1646 "       color.rgb *= LightColor;\n"
1647 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1648 "#if defined(USESHADOWMAP2D)\n"
1649 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1650 "#endif\n"
1651 "# ifdef USECUBEFILTER\n"
1652 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1653 "# endif\n"
1654 "#endif // MODE_LIGHTSOURCE\n"
1655 "\n"
1656 "\n"
1657 "\n"
1658 "\n"
1659 "#ifdef MODE_LIGHTDIRECTION\n"
1660 "#define SHADING\n"
1661 "#ifdef USEDIFFUSE\n"
1662 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1663 "#endif\n"
1664 "#define lightcolor LightColor\n"
1665 "#endif // MODE_LIGHTDIRECTION\n"
1666 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1667 "#define SHADING\n"
1668 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1669 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1670 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1671 "       // convert modelspace light vector to tangentspace\n"
1672 "       myhalf3 lightnormal;\n"
1673 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1674 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1675 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1676 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1677 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1678 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1679 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1680 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1681 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1682 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1683 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1684 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1685 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1686 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1687 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1688 "#define SHADING\n"
1689 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1690 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1691 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1692 "#endif\n"
1693 "\n"
1694 "\n"
1695 "\n"
1696 "\n"
1697 "#ifdef MODE_FAKELIGHT\n"
1698 "#define SHADING\n"
1699 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1700 "myhalf3 lightcolor = myhalf3(1.0);\n"
1701 "#endif // MODE_FAKELIGHT\n"
1702 "\n"
1703 "\n"
1704 "\n"
1705 "\n"
1706 "#ifdef MODE_LIGHTMAP\n"
1707 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1708 "#endif // MODE_LIGHTMAP\n"
1709 "#ifdef MODE_VERTEXCOLOR\n"
1710 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1711 "#endif // MODE_VERTEXCOLOR\n"
1712 "#ifdef MODE_FLATCOLOR\n"
1713 "       color.rgb = diffusetex * Color_Ambient;\n"
1714 "#endif // MODE_FLATCOLOR\n"
1715 "\n"
1716 "\n"
1717 "\n"
1718 "\n"
1719 "#ifdef SHADING\n"
1720 "# ifdef USEDIFFUSE\n"
1721 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1722 "#  ifdef USESPECULAR\n"
1723 "#   ifdef USEEXACTSPECULARMATH\n"
1724 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1725 "#   else\n"
1726 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1727 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1728 "#   endif\n"
1729 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1730 "#  else\n"
1731 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1732 "#  endif\n"
1733 "# else\n"
1734 "       color.rgb = diffusetex * Color_Ambient;\n"
1735 "# endif\n"
1736 "#endif\n"
1737 "\n"
1738 "#ifdef USESHADOWMAPORTHO\n"
1739 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1740 "#endif\n"
1741 "\n"
1742 "#ifdef USEDEFERREDLIGHTMAP\n"
1743 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1744 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1745 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1746 "#endif\n"
1747 "\n"
1748 "#ifdef USEGLOW\n"
1749 "#ifdef USEVERTEXTEXTUREBLEND\n"
1750 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1751 "#else\n"
1752 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1753 "#endif\n"
1754 "#endif\n"
1755 "\n"
1756 "#ifdef USEFOG\n"
1757 "       color.rgb = FogVertex(color.rgb);\n"
1758 "#endif\n"
1759 "\n"
1760 "       // 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"
1761 "#ifdef USEREFLECTION\n"
1762 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1763 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1764 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1765 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1766 "       // FIXME temporary hack to detect the case that the reflection\n"
1767 "       // gets blackened at edges due to leaving the area that contains actual\n"
1768 "       // content.\n"
1769 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1770 "       // 'appening.\n"
1771 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1772 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1773 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1774 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1775 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1776 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1777 "#endif\n"
1778 "\n"
1779 "       gl_FragColor = vec4(color);\n"
1780 "}\n"
1781 "#endif // FRAGMENT_SHADER\n"
1782 "\n"
1783 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1784 "#endif // !MODE_DEFERREDGEOMETRY\n"
1785 "#endif // !MODE_WATER\n"
1786 "#endif // !MODE_REFRACTION\n"
1787 "#endif // !MODE_BLOOMBLUR\n"
1788 "#endif // !MODE_GENERIC\n"
1789 "#endif // !MODE_POSTPROCESS\n"
1790 "#endif // !MODE_SHOWDEPTH\n"
1791 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1792 ;
1793
1794 /*
1795 =========================================================================================================================================================
1796
1797
1798
1799 =========================================================================================================================================================
1800
1801
1802
1803 =========================================================================================================================================================
1804
1805
1806
1807 =========================================================================================================================================================
1808
1809
1810
1811 =========================================================================================================================================================
1812
1813
1814
1815 =========================================================================================================================================================
1816
1817
1818
1819 =========================================================================================================================================================
1820 */
1821
1822 const char *builtincgshaderstring =
1823 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1824 "// written by Forest 'LordHavoc' Hale\n"
1825 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1826 "\n"
1827 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1828 "#if defined(USEREFLECTION)\n"
1829 "#undef USESHADOWMAPORTHO\n"
1830 "#endif\n"
1831 "\n"
1832 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1833 "# define USEFOG\n"
1834 "#endif\n"
1835 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1836 "#define USELIGHTMAP\n"
1837 "#endif\n"
1838 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1839 "#define USEEYEVECTOR\n"
1840 "#endif\n"
1841 "\n"
1842 "#ifdef FRAGMENT_SHADER\n"
1843 "#ifdef HLSL\n"
1844 "//#undef USESHADOWMAPPCF\n"
1845 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1846 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1847 "#else\n"
1848 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1849 "#endif\n"
1850 "#endif\n"
1851 "\n"
1852 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1853 "#ifdef VERTEX_SHADER\n"
1854 "void main\n"
1855 "(\n"
1856 "float4 gl_Vertex : POSITION,\n"
1857 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1858 "out float4 gl_Position : POSITION,\n"
1859 "out float Depth : TEXCOORD0\n"
1860 ")\n"
1861 "{\n"
1862 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1863 "       Depth = gl_Position.z;\n"
1864 "}\n"
1865 "#endif\n"
1866 "\n"
1867 "#ifdef FRAGMENT_SHADER\n"
1868 "void main\n"
1869 "(\n"
1870 "float Depth : TEXCOORD0,\n"
1871 "out float4 gl_FragColor : COLOR\n"
1872 ")\n"
1873 "{\n"
1874 "//     float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1875 "       float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1876 "       temp.yz -= floor(temp.yz);\n"
1877 "       gl_FragColor = temp;\n"
1878 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1879 "}\n"
1880 "#endif\n"
1881 "#else // !MODE_DEPTH_ORSHADOW\n"
1882 "\n"
1883 "\n"
1884 "\n"
1885 "\n"
1886 "#ifdef MODE_SHOWDEPTH\n"
1887 "#ifdef VERTEX_SHADER\n"
1888 "void main\n"
1889 "(\n"
1890 "float4 gl_Vertex : POSITION,\n"
1891 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1892 "out float4 gl_Position : POSITION,\n"
1893 "out float4 gl_FrontColor : COLOR0\n"
1894 ")\n"
1895 "{\n"
1896 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1897 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1898 "}\n"
1899 "#endif\n"
1900 "\n"
1901 "#ifdef FRAGMENT_SHADER\n"
1902 "void main\n"
1903 "(\n"
1904 "float4 gl_FrontColor : COLOR0,\n"
1905 "out float4 gl_FragColor : COLOR\n"
1906 ")\n"
1907 "{\n"
1908 "       gl_FragColor = gl_FrontColor;\n"
1909 "}\n"
1910 "#endif\n"
1911 "#else // !MODE_SHOWDEPTH\n"
1912 "\n"
1913 "\n"
1914 "\n"
1915 "\n"
1916 "#ifdef MODE_POSTPROCESS\n"
1917 "\n"
1918 "#ifdef VERTEX_SHADER\n"
1919 "void main\n"
1920 "(\n"
1921 "float4 gl_Vertex : POSITION,\n"
1922 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1923 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1924 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1925 "out float4 gl_Position : POSITION,\n"
1926 "out float2 TexCoord1 : TEXCOORD0,\n"
1927 "out float2 TexCoord2 : TEXCOORD1\n"
1928 ")\n"
1929 "{\n"
1930 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1931 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1932 "#ifdef USEBLOOM\n"
1933 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1934 "#endif\n"
1935 "}\n"
1936 "#endif\n"
1937 "\n"
1938 "#ifdef FRAGMENT_SHADER\n"
1939 "void main\n"
1940 "(\n"
1941 "float2 TexCoord1 : TEXCOORD0,\n"
1942 "float2 TexCoord2 : TEXCOORD1,\n"
1943 "uniform sampler Texture_First : register(s0),\n"
1944 "#ifdef USEBLOOM\n"
1945 "uniform sampler Texture_Second : register(s1),\n"
1946 "#endif\n"
1947 "#ifdef USEGAMMARAMPS\n"
1948 "uniform sampler Texture_GammaRamps : register(s2),\n"
1949 "#endif\n"
1950 "#ifdef USESATURATION\n"
1951 "uniform float Saturation : register(c30),\n"
1952 "#endif\n"
1953 "#ifdef USEVIEWTINT\n"
1954 "uniform float4 ViewTintColor : register(c41),\n"
1955 "#endif\n"
1956 "uniform float4 UserVec1 : register(c37),\n"
1957 "uniform float4 UserVec2 : register(c38),\n"
1958 "uniform float4 UserVec3 : register(c39),\n"
1959 "uniform float4 UserVec4 : register(c40),\n"
1960 "uniform float ClientTime : register(c2),\n"
1961 "uniform float2 PixelSize : register(c25),\n"
1962 "uniform float4 BloomColorSubtract : register(c43),\n"
1963 "out float4 gl_FragColor : COLOR\n"
1964 ")\n"
1965 "{\n"
1966 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1967 "#ifdef USEBLOOM\n"
1968 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1969 "#endif\n"
1970 "#ifdef USEVIEWTINT\n"
1971 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1972 "#endif\n"
1973 "\n"
1974 "#ifdef USEPOSTPROCESSING\n"
1975 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1976 "// 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"
1977 "       float sobel = 1.0;\n"
1978 "       // float2 ts = textureSize(Texture_First, 0);\n"
1979 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
1980 "       float2 px = PixelSize;\n"
1981 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1982 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
1983 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1984 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1985 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
1986 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1987 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1988 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
1989 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1990 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1991 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
1992 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1993 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
1994 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
1995 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
1996 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
1997 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
1998 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
1999 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2000 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2001 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2002 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2003 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2004 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2005 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2006 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2007 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2008 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2009 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2010 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2011 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2012 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2013 "#endif\n"
2014 "\n"
2015 "#ifdef USESATURATION\n"
2016 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2017 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2018 "       // 'vampire sight' effect, wheres red is compensated\n"
2019 "       #ifdef SATURATION_REDCOMPENSATE\n"
2020 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2021 "               gl_FragColor.rgb = mix(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2022 "               gl_FragColor.r += r;\n"
2023 "       #else\n"
2024 "               // normal desaturation\n"
2025 "               //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2026 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2027 "       #endif\n"
2028 "#endif\n"
2029 "\n"
2030 "#ifdef USEGAMMARAMPS\n"
2031 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2032 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2033 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2034 "#endif\n"
2035 "}\n"
2036 "#endif\n"
2037 "#else // !MODE_POSTPROCESS\n"
2038 "\n"
2039 "\n"
2040 "\n"
2041 "\n"
2042 "#ifdef MODE_GENERIC\n"
2043 "#ifdef VERTEX_SHADER\n"
2044 "void main\n"
2045 "(\n"
2046 "float4 gl_Vertex : POSITION,\n"
2047 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2048 "float4 gl_Color : COLOR0,\n"
2049 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2050 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2051 "out float4 gl_Position : POSITION,\n"
2052 "#ifdef USEDIFFUSE\n"
2053 "out float2 TexCoord1 : TEXCOORD0,\n"
2054 "#endif\n"
2055 "#ifdef USESPECULAR\n"
2056 "out float2 TexCoord2 : TEXCOORD1,\n"
2057 "#endif\n"
2058 "out float4 gl_FrontColor : COLOR\n"
2059 ")\n"
2060 "{\n"
2061 "#ifdef HLSL\n"
2062 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2063 "#else\n"
2064 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2065 "#endif\n"
2066 "#ifdef USEDIFFUSE\n"
2067 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2068 "#endif\n"
2069 "#ifdef USESPECULAR\n"
2070 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2071 "#endif\n"
2072 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2073 "}\n"
2074 "#endif\n"
2075 "\n"
2076 "#ifdef FRAGMENT_SHADER\n"
2077 "\n"
2078 "void main\n"
2079 "(\n"
2080 "float4 gl_FrontColor : COLOR0,\n"
2081 "float2 TexCoord1 : TEXCOORD0,\n"
2082 "float2 TexCoord2 : TEXCOORD1,\n"
2083 "#ifdef USEDIFFUSE\n"
2084 "uniform sampler Texture_First : register(s0),\n"
2085 "#endif\n"
2086 "#ifdef USESPECULAR\n"
2087 "uniform sampler Texture_Second : register(s1),\n"
2088 "#endif\n"
2089 "out float4 gl_FragColor : COLOR\n"
2090 ")\n"
2091 "{\n"
2092 "       gl_FragColor = gl_FrontColor;\n"
2093 "#ifdef USEDIFFUSE\n"
2094 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2095 "#endif\n"
2096 "\n"
2097 "#ifdef USESPECULAR\n"
2098 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2099 "# ifdef USECOLORMAPPING\n"
2100 "       gl_FragColor *= tex2;\n"
2101 "# endif\n"
2102 "# ifdef USEGLOW\n"
2103 "       gl_FragColor += tex2;\n"
2104 "# endif\n"
2105 "# ifdef USEVERTEXTEXTUREBLEND\n"
2106 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2107 "# endif\n"
2108 "#endif\n"
2109 "}\n"
2110 "#endif\n"
2111 "#else // !MODE_GENERIC\n"
2112 "\n"
2113 "\n"
2114 "\n"
2115 "\n"
2116 "#ifdef MODE_BLOOMBLUR\n"
2117 "#ifdef VERTEX_SHADER\n"
2118 "void main\n"
2119 "(\n"
2120 "float4 gl_Vertex : POSITION,\n"
2121 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2122 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2123 "out float4 gl_Position : POSITION,\n"
2124 "out float2 TexCoord : TEXCOORD0\n"
2125 ")\n"
2126 "{\n"
2127 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2128 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2129 "}\n"
2130 "#endif\n"
2131 "\n"
2132 "#ifdef FRAGMENT_SHADER\n"
2133 "\n"
2134 "void main\n"
2135 "(\n"
2136 "float2 TexCoord : TEXCOORD0,\n"
2137 "uniform sampler Texture_First : register(s0),\n"
2138 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2139 "out float4 gl_FragColor : COLOR\n"
2140 ")\n"
2141 "{\n"
2142 "       int i;\n"
2143 "       float2 tc = TexCoord;\n"
2144 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2145 "       tc += BloomBlur_Parameters.xy;\n"
2146 "       for (i = 1;i < SAMPLES;i++)\n"
2147 "       {\n"
2148 "               color += tex2D(Texture_First, tc).rgb;\n"
2149 "               tc += BloomBlur_Parameters.xy;\n"
2150 "       }\n"
2151 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2152 "}\n"
2153 "#endif\n"
2154 "#else // !MODE_BLOOMBLUR\n"
2155 "#ifdef MODE_REFRACTION\n"
2156 "#ifdef VERTEX_SHADER\n"
2157 "void main\n"
2158 "(\n"
2159 "float4 gl_Vertex : POSITION,\n"
2160 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2161 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2162 "uniform float4x4 TexMatrix : register(c0),\n"
2163 "uniform float3 EyePosition : register(c24),\n"
2164 "out float4 gl_Position : POSITION,\n"
2165 "out float2 TexCoord : TEXCOORD0,\n"
2166 "out float3 EyeVector : TEXCOORD1,\n"
2167 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2168 ")\n"
2169 "{\n"
2170 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2171 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2172 "       ModelViewProjectionPosition = gl_Position;\n"
2173 "}\n"
2174 "#endif\n"
2175 "\n"
2176 "#ifdef FRAGMENT_SHADER\n"
2177 "void main\n"
2178 "(\n"
2179 "float2 TexCoord : TEXCOORD0,\n"
2180 "float3 EyeVector : TEXCOORD1,\n"
2181 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2182 "uniform sampler Texture_Normal : register(s0),\n"
2183 "uniform sampler Texture_Refraction : register(s3),\n"
2184 "uniform sampler Texture_Reflection : register(s7),\n"
2185 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2186 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2187 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2188 "uniform float4 RefractColor : register(c29),\n"
2189 "out float4 gl_FragColor : COLOR\n"
2190 ")\n"
2191 "{\n"
2192 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2193 "       //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"
2194 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2195 "       float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2196 "       // FIXME temporary hack to detect the case that the reflection\n"
2197 "       // gets blackened at edges due to leaving the area that contains actual\n"
2198 "       // content.\n"
2199 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2200 "       // 'appening.\n"
2201 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2202 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2203 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2204 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2205 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2206 "       gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2207 "}\n"
2208 "#endif\n"
2209 "#else // !MODE_REFRACTION\n"
2210 "\n"
2211 "\n"
2212 "\n"
2213 "\n"
2214 "#ifdef MODE_WATER\n"
2215 "#ifdef VERTEX_SHADER\n"
2216 "\n"
2217 "void main\n"
2218 "(\n"
2219 "float4 gl_Vertex : POSITION,\n"
2220 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2221 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2222 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2223 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2224 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2225 "uniform float4x4 TexMatrix : register(c0),\n"
2226 "uniform float3 EyePosition : register(c24),\n"
2227 "out float4 gl_Position : POSITION,\n"
2228 "out float2 TexCoord : TEXCOORD0,\n"
2229 "out float3 EyeVector : TEXCOORD1,\n"
2230 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2231 ")\n"
2232 "{\n"
2233 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2234 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2235 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2236 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2237 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2238 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2239 "       ModelViewProjectionPosition = gl_Position;\n"
2240 "}\n"
2241 "#endif\n"
2242 "\n"
2243 "#ifdef FRAGMENT_SHADER\n"
2244 "void main\n"
2245 "(\n"
2246 "float2 TexCoord : TEXCOORD0,\n"
2247 "float3 EyeVector : TEXCOORD1,\n"
2248 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2249 "uniform sampler Texture_Normal : register(s0),\n"
2250 "uniform sampler Texture_Refraction : register(s3),\n"
2251 "uniform sampler Texture_Reflection : register(s7),\n"
2252 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2253 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2254 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2255 "uniform float4 RefractColor : register(c29),\n"
2256 "uniform float4 ReflectColor : register(c26),\n"
2257 "uniform float ReflectFactor : register(c27),\n"
2258 "uniform float ReflectOffset : register(c28),\n"
2259 "out float4 gl_FragColor : COLOR\n"
2260 ")\n"
2261 "{\n"
2262 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2263 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2264 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2265 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2266 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2267 "       // FIXME temporary hack to detect the case that the reflection\n"
2268 "       // gets blackened at edges due to leaving the area that contains actual\n"
2269 "       // content.\n"
2270 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2271 "       // 'appening.\n"
2272 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2273 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2274 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2275 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2276 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2277 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2278 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2279 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2280 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2281 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2282 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2283 "       gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2284 "}\n"
2285 "#endif\n"
2286 "#else // !MODE_WATER\n"
2287 "\n"
2288 "\n"
2289 "\n"
2290 "\n"
2291 "// 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"
2292 "\n"
2293 "// fragment shader specific:\n"
2294 "#ifdef FRAGMENT_SHADER\n"
2295 "\n"
2296 "#ifdef USEFOG\n"
2297 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2298 "{\n"
2299 "       float fogfrac;\n"
2300 "#ifdef USEFOGHEIGHTTEXTURE\n"
2301 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2302 "       fogfrac = fogheightpixel.a;\n"
2303 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2304 "#else\n"
2305 "# ifdef USEFOGOUTSIDE\n"
2306 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2307 "# else\n"
2308 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2309 "# endif\n"
2310 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2311 "#endif\n"
2312 "}\n"
2313 "#endif\n"
2314 "\n"
2315 "#ifdef USEOFFSETMAPPING\n"
2316 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2317 "{\n"
2318 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2319 "       // 14 sample relief mapping: linear search and then binary search\n"
2320 "       // this basically steps forward a small amount repeatedly until it finds\n"
2321 "       // itself inside solid, then jitters forward and back using decreasing\n"
2322 "       // amounts to find the impact\n"
2323 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2324 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2325 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2326 "       float3 RT = float3(TexCoord, 1);\n"
2327 "       OffsetVector *= 0.1;\n"
2328 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2329 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2330 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2331 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2332 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2333 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2334 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2335 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\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)          - 0.5);\n"
2338 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2339 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2340 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2341 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2342 "       return RT.xy;\n"
2343 "#else\n"
2344 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2345 "       // this basically moves forward the full distance, and then backs up based\n"
2346 "       // on height of samples\n"
2347 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2348 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2349 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2350 "       TexCoord += OffsetVector;\n"
2351 "       OffsetVector *= 0.333;\n"
2352 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2353 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2354 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2355 "       return TexCoord;\n"
2356 "#endif\n"
2357 "}\n"
2358 "#endif // USEOFFSETMAPPING\n"
2359 "\n"
2360 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2361 "#if defined(USESHADOWMAP2D)\n"
2362 "# ifdef USESHADOWMAPORTHO\n"
2363 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2364 "# else\n"
2365 "#  ifdef USESHADOWMAPVSDCT\n"
2366 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2367 "{\n"
2368 "       float3 adir = abs(dir);\n"
2369 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2370 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2371 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2372 "}\n"
2373 "#  else\n"
2374 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2375 "{\n"
2376 "       float3 adir = abs(dir);\n"
2377 "       float ma = adir.z;\n"
2378 "       float4 proj = float4(dir, 2.5);\n"
2379 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2380 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2381 "#ifdef HLSL\n"
2382 "       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"
2383 "#else\n"
2384 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2385 "       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"
2386 "#endif\n"
2387 "}\n"
2388 "#  endif\n"
2389 "# endif\n"
2390 "#endif // defined(USESHADOWMAP2D)\n"
2391 "\n"
2392 "# ifdef USESHADOWMAP2D\n"
2393 "#ifdef USESHADOWMAPVSDCT\n"
2394 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2395 "#else\n"
2396 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2397 "#endif\n"
2398 "{\n"
2399 "#ifdef USESHADOWMAPVSDCT\n"
2400 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2401 "#else\n"
2402 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2403 "#endif\n"
2404 "       float f;\n"
2405 "\n"
2406 "#  ifdef USESHADOWSAMPLER\n"
2407 "#    ifdef USESHADOWMAPPCF\n"
2408 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2409 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2410 "       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"
2411 "#    else\n"
2412 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2413 "#    endif\n"
2414 "#  else\n"
2415 "#    ifdef USESHADOWMAPPCF\n"
2416 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2417 "#      ifdef GL_ARB_texture_gather\n"
2418 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2419 "#      else\n"
2420 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2421 "#      endif\n"
2422 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2423 "#      if USESHADOWMAPPCF > 1\n"
2424 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2425 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2426 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2427 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2428 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2429 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2430 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2431 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2432 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2433 "       float4 locols = float4(group1.ab, group3.ab);\n"
2434 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2435 "       locols.yz += group2.ab;\n"
2436 "       hicols.yz += group8.rg;\n"
2437 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2438 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2439 "                               lerp(locols, hicols, offset.y);\n"
2440 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2441 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2442 "       f = dot(cols, float4(1.0/25.0));\n"
2443 "#      else\n"
2444 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2445 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2446 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2447 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2448 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2449 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2450 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2451 "#      endif\n"
2452 "#     else\n"
2453 "#      ifdef GL_EXT_gpu_shader4\n"
2454 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2455 "#      else\n"
2456 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2457 "#      endif\n"
2458 "#      if USESHADOWMAPPCF > 1\n"
2459 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2460 "       center *= ShadowMap_TextureScale;\n"
2461 "       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"
2462 "       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"
2463 "       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"
2464 "       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"
2465 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2466 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2467 "#      else\n"
2468 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2469 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2470 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2471 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2472 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2473 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2474 "#      endif\n"
2475 "#     endif\n"
2476 "#    else\n"
2477 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2478 "#    endif\n"
2479 "#  endif\n"
2480 "#  ifdef USESHADOWMAPORTHO\n"
2481 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2482 "#  else\n"
2483 "       return f;\n"
2484 "#  endif\n"
2485 "}\n"
2486 "# endif\n"
2487 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2488 "#endif // FRAGMENT_SHADER\n"
2489 "\n"
2490 "\n"
2491 "\n"
2492 "\n"
2493 "#ifdef MODE_DEFERREDGEOMETRY\n"
2494 "#ifdef VERTEX_SHADER\n"
2495 "void main\n"
2496 "(\n"
2497 "float4 gl_Vertex : POSITION,\n"
2498 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2499 "#ifdef USEVERTEXTEXTUREBLEND\n"
2500 "float4 gl_Color : COLOR0,\n"
2501 "#endif\n"
2502 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2503 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2504 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2505 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2506 "uniform float4x4 TexMatrix : register(c0),\n"
2507 "#ifdef USEVERTEXTEXTUREBLEND\n"
2508 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2509 "#endif\n"
2510 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2511 "#ifdef USEOFFSETMAPPING\n"
2512 "uniform float3 EyePosition : register(c24),\n"
2513 "#endif\n"
2514 "out float4 gl_Position : POSITION,\n"
2515 "#ifdef USEVERTEXTEXTUREBLEND\n"
2516 "out float4 gl_FrontColor : COLOR,\n"
2517 "#endif\n"
2518 "out float4 TexCoordBoth : TEXCOORD0,\n"
2519 "#ifdef USEOFFSETMAPPING\n"
2520 "out float3 EyeVector : TEXCOORD2,\n"
2521 "#endif\n"
2522 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2523 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2524 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2525 ")\n"
2526 "{\n"
2527 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2528 "#ifdef USEVERTEXTEXTUREBLEND\n"
2529 "#ifdef HLSL\n"
2530 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2531 "#else\n"
2532 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2533 "#endif\n"
2534 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2535 "#endif\n"
2536 "\n"
2537 "       // transform unnormalized eye direction into tangent space\n"
2538 "#ifdef USEOFFSETMAPPING\n"
2539 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2540 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2541 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2542 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2543 "#endif\n"
2544 "\n"
2545 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2546 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2547 "       VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2548 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2549 "       VectorR.w = gl_Position.z;\n"
2550 "}\n"
2551 "#endif // VERTEX_SHADER\n"
2552 "\n"
2553 "#ifdef FRAGMENT_SHADER\n"
2554 "void main\n"
2555 "(\n"
2556 "float4 TexCoordBoth : TEXCOORD0,\n"
2557 "float3 EyeVector : TEXCOORD2,\n"
2558 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2559 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2560 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2561 "uniform sampler Texture_Normal : register(s0),\n"
2562 "#ifdef USEALPHAKILL\n"
2563 "uniform sampler Texture_Color : register(s1),\n"
2564 "#endif\n"
2565 "uniform sampler Texture_Gloss : register(s2),\n"
2566 "#ifdef USEVERTEXTEXTUREBLEND\n"
2567 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2568 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2569 "#endif\n"
2570 "#ifdef USEOFFSETMAPPING\n"
2571 "uniform float OffsetMapping_Scale : register(c24),\n"
2572 "#endif\n"
2573 "uniform half SpecularPower : register(c36),\n"
2574 "#ifdef HLSL\n"
2575 "out float4 gl_FragData0 : COLOR0,\n"
2576 "out float4 gl_FragData1 : COLOR1\n"
2577 "#else\n"
2578 "out float4 gl_FragColor : COLOR\n"
2579 "#endif\n"
2580 ")\n"
2581 "{\n"
2582 "       float2 TexCoord = TexCoordBoth.xy;\n"
2583 "#ifdef USEOFFSETMAPPING\n"
2584 "       // apply offsetmapping\n"
2585 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2586 "#define TexCoord TexCoordOffset\n"
2587 "#endif\n"
2588 "\n"
2589 "#ifdef USEALPHAKILL\n"
2590 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2591 "               discard;\n"
2592 "#endif\n"
2593 "\n"
2594 "#ifdef USEVERTEXTEXTUREBLEND\n"
2595 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2596 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2597 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2598 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2599 "#endif\n"
2600 "\n"
2601 "#ifdef USEVERTEXTEXTUREBLEND\n"
2602 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2603 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2604 "#else\n"
2605 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2606 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2607 "#endif\n"
2608 "\n"
2609 "#ifdef HLSL\n"
2610 "       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"
2611 "       float Depth = VectorR.w / 256.0;\n"
2612 "       float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2613 "//     float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2614 "       depthcolor.yz -= floor(depthcolor.yz);\n"
2615 "       gl_FragData1 = depthcolor;\n"
2616 "#else\n"
2617 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2618 "#endif\n"
2619 "}\n"
2620 "#endif // FRAGMENT_SHADER\n"
2621 "#else // !MODE_DEFERREDGEOMETRY\n"
2622 "\n"
2623 "\n"
2624 "\n"
2625 "\n"
2626 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2627 "#ifdef VERTEX_SHADER\n"
2628 "void main\n"
2629 "(\n"
2630 "float4 gl_Vertex : POSITION,\n"
2631 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2632 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2633 "out float4 gl_Position : POSITION,\n"
2634 "out float4 ModelViewPosition : TEXCOORD0\n"
2635 ")\n"
2636 "{\n"
2637 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2638 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2639 "}\n"
2640 "#endif // VERTEX_SHADER\n"
2641 "\n"
2642 "#ifdef FRAGMENT_SHADER\n"
2643 "void main\n"
2644 "(\n"
2645 "#ifdef HLSL\n"
2646 "float2 Pixel : VPOS,\n"
2647 "#else\n"
2648 "float2 Pixel : WPOS,\n"
2649 "#endif\n"
2650 "float4 ModelViewPosition : TEXCOORD0,\n"
2651 "uniform float4x4 ViewToLight : register(c44),\n"
2652 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2653 "uniform float3 LightPosition : register(c23),\n"
2654 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2655 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2656 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2657 "#ifdef USESPECULAR\n"
2658 "uniform half3 DeferredColor_Specular : register(c11),\n"
2659 "uniform half SpecularPower : register(c36),\n"
2660 "#endif\n"
2661 "uniform sampler Texture_Attenuation : register(s9),\n"
2662 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2663 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2664 "\n"
2665 "#ifdef USECUBEFILTER\n"
2666 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2667 "#endif\n"
2668 "\n"
2669 "#ifdef USESHADOWMAP2D\n"
2670 "# ifdef USESHADOWSAMPLER\n"
2671 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2672 "# else\n"
2673 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2674 "# endif\n"
2675 "#endif\n"
2676 "\n"
2677 "#ifdef USESHADOWMAPVSDCT\n"
2678 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2679 "#endif\n"
2680 "\n"
2681 "#if defined(USESHADOWMAP2D)\n"
2682 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2683 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2684 "#endif\n"
2685 "\n"
2686 "out float4 gl_FragData0 : COLOR0,\n"
2687 "out float4 gl_FragData1 : COLOR1\n"
2688 ")\n"
2689 "{\n"
2690 "       // calculate viewspace pixel position\n"
2691 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2692 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2693 "       float3 position;\n"
2694 "#ifdef HLSL\n"
2695 "       position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2696 "#else\n"
2697 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2698 "#endif\n"
2699 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2700 "       // decode viewspace pixel normal\n"
2701 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2702 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2703 "       // surfacenormal = pixel normal in viewspace\n"
2704 "       // LightVector = pixel to light in viewspace\n"
2705 "       // CubeVector = position in lightspace\n"
2706 "       // eyevector = pixel to view in viewspace\n"
2707 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2708 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2709 "#ifdef USEDIFFUSE\n"
2710 "       // calculate diffuse shading\n"
2711 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2712 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2713 "#endif\n"
2714 "#ifdef USESPECULAR\n"
2715 "       // calculate directional shading\n"
2716 "       float3 eyevector = position * -1.0;\n"
2717 "#  ifdef USEEXACTSPECULARMATH\n"
2718 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2719 "#  else\n"
2720 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2721 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2722 "#  endif\n"
2723 "#endif\n"
2724 "\n"
2725 "#if defined(USESHADOWMAP2D)\n"
2726 "       fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2727 "#ifdef USESHADOWMAPVSDCT\n"
2728 ", Texture_CubeProjection\n"
2729 "#endif\n"
2730 "       ));\n"
2731 "#endif\n"
2732 "\n"
2733 "#ifdef USEDIFFUSE\n"
2734 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2735 "#else\n"
2736 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2737 "#endif\n"
2738 "#ifdef USESPECULAR\n"
2739 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2740 "#else\n"
2741 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2742 "#endif\n"
2743 "\n"
2744 "# ifdef USECUBEFILTER\n"
2745 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2746 "       gl_FragData0.rgb *= cubecolor;\n"
2747 "       gl_FragData1.rgb *= cubecolor;\n"
2748 "# endif\n"
2749 "}\n"
2750 "#endif // FRAGMENT_SHADER\n"
2751 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2752 "\n"
2753 "\n"
2754 "\n"
2755 "\n"
2756 "#ifdef VERTEX_SHADER\n"
2757 "void main\n"
2758 "(\n"
2759 "float4 gl_Vertex : POSITION,\n"
2760 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2761 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2762 "float4 gl_Color : COLOR0,\n"
2763 "#endif\n"
2764 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2765 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2766 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2767 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2768 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2769 "\n"
2770 "uniform float3 EyePosition : register(c24),\n"
2771 "uniform float4x4 TexMatrix : register(c0),\n"
2772 "#ifdef USEVERTEXTEXTUREBLEND\n"
2773 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2774 "#endif\n"
2775 "#ifdef MODE_LIGHTSOURCE\n"
2776 "uniform float4x4 ModelToLight : register(c20),\n"
2777 "#endif\n"
2778 "#ifdef MODE_LIGHTSOURCE\n"
2779 "uniform float3 LightPosition : register(c27),\n"
2780 "#endif\n"
2781 "#ifdef MODE_LIGHTDIRECTION\n"
2782 "uniform float3 LightDir : register(c26),\n"
2783 "#endif\n"
2784 "uniform float4 FogPlane : register(c25),\n"
2785 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2786 "uniform float3 LightPosition : register(c27),\n"
2787 "#endif\n"
2788 "#ifdef USESHADOWMAPORTHO\n"
2789 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2790 "#endif\n"
2791 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2792 "out float4 gl_FrontColor : COLOR,\n"
2793 "#endif\n"
2794 "out float4 TexCoordBoth : TEXCOORD0,\n"
2795 "#ifdef USELIGHTMAP\n"
2796 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2797 "#endif\n"
2798 "#ifdef USEEYEVECTOR\n"
2799 "out float3 EyeVector : TEXCOORD2,\n"
2800 "#endif\n"
2801 "#ifdef USEREFLECTION\n"
2802 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2803 "#endif\n"
2804 "#ifdef USEFOG\n"
2805 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2806 "#endif\n"
2807 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2808 "out float3 LightVector : TEXCOORD1,\n"
2809 "#endif\n"
2810 "#ifdef MODE_LIGHTSOURCE\n"
2811 "out float3 CubeVector : TEXCOORD3,\n"
2812 "#endif\n"
2813 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2814 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2815 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2816 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2817 "#endif\n"
2818 "#ifdef USESHADOWMAPORTHO\n"
2819 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2820 "#endif\n"
2821 "out float4 gl_Position : POSITION\n"
2822 ")\n"
2823 "{\n"
2824 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2825 "#ifdef HLSL\n"
2826 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2827 "#else\n"
2828 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2829 "#endif\n"
2830 "#endif\n"
2831 "       // copy the surface texcoord\n"
2832 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2833 "#ifdef USEVERTEXTEXTUREBLEND\n"
2834 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2835 "#endif\n"
2836 "#ifdef USELIGHTMAP\n"
2837 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2838 "#endif\n"
2839 "\n"
2840 "#ifdef MODE_LIGHTSOURCE\n"
2841 "       // transform vertex position into light attenuation/cubemap space\n"
2842 "       // (-1 to +1 across the light box)\n"
2843 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2844 "\n"
2845 "# ifdef USEDIFFUSE\n"
2846 "       // transform unnormalized light direction into tangent space\n"
2847 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2848 "       //  normalize it per pixel)\n"
2849 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2850 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2851 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2852 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2853 "# endif\n"
2854 "#endif\n"
2855 "\n"
2856 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2857 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2858 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2859 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2860 "#endif\n"
2861 "\n"
2862 "       // transform unnormalized eye direction into tangent space\n"
2863 "#ifdef USEEYEVECTOR\n"
2864 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2865 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2866 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2867 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2868 "#endif\n"
2869 "\n"
2870 "#ifdef USEFOG\n"
2871 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2872 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2873 "#endif\n"
2874 "\n"
2875 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2876 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2877 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2878 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2879 "#endif\n"
2880 "\n"
2881 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2882 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2883 "\n"
2884 "#ifdef USESHADOWMAPORTHO\n"
2885 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2886 "#endif\n"
2887 "\n"
2888 "#ifdef USEREFLECTION\n"
2889 "       ModelViewProjectionPosition = gl_Position;\n"
2890 "#endif\n"
2891 "}\n"
2892 "#endif // VERTEX_SHADER\n"
2893 "\n"
2894 "\n"
2895 "\n"
2896 "\n"
2897 "#ifdef FRAGMENT_SHADER\n"
2898 "void main\n"
2899 "(\n"
2900 "#ifdef USEDEFERREDLIGHTMAP\n"
2901 "#ifdef HLSL\n"
2902 "float2 Pixel : VPOS,\n"
2903 "#else\n"
2904 "float2 Pixel : WPOS,\n"
2905 "#endif\n"
2906 "#endif\n"
2907 "float4 gl_FrontColor : COLOR,\n"
2908 "float4 TexCoordBoth : TEXCOORD0,\n"
2909 "#ifdef USELIGHTMAP\n"
2910 "float2 TexCoordLightmap : TEXCOORD1,\n"
2911 "#endif\n"
2912 "#ifdef USEEYEVECTOR\n"
2913 "float3 EyeVector : TEXCOORD2,\n"
2914 "#endif\n"
2915 "#ifdef USEREFLECTION\n"
2916 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2917 "#endif\n"
2918 "#ifdef USEFOG\n"
2919 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2920 "#endif\n"
2921 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2922 "float3 LightVector : TEXCOORD1,\n"
2923 "#endif\n"
2924 "#ifdef MODE_LIGHTSOURCE\n"
2925 "float3 CubeVector : TEXCOORD3,\n"
2926 "#endif\n"
2927 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2928 "float4 ModelViewPosition : TEXCOORD0,\n"
2929 "#endif\n"
2930 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2931 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2932 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2933 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2934 "#endif\n"
2935 "#ifdef USESHADOWMAPORTHO\n"
2936 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2937 "#endif\n"
2938 "\n"
2939 "uniform sampler Texture_Normal : register(s0),\n"
2940 "uniform sampler Texture_Color : register(s1),\n"
2941 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2942 "uniform sampler Texture_Gloss : register(s2),\n"
2943 "#endif\n"
2944 "#ifdef USEGLOW\n"
2945 "uniform sampler Texture_Glow : register(s3),\n"
2946 "#endif\n"
2947 "#ifdef USEVERTEXTEXTUREBLEND\n"
2948 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2949 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2950 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2951 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2952 "#endif\n"
2953 "#ifdef USEGLOW\n"
2954 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2955 "#endif\n"
2956 "#endif\n"
2957 "#ifdef USECOLORMAPPING\n"
2958 "uniform sampler Texture_Pants : register(s4),\n"
2959 "uniform sampler Texture_Shirt : register(s7),\n"
2960 "#endif\n"
2961 "#ifdef USEFOG\n"
2962 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2963 "uniform sampler Texture_FogMask : register(s8),\n"
2964 "#endif\n"
2965 "#ifdef USELIGHTMAP\n"
2966 "uniform sampler Texture_Lightmap : register(s9),\n"
2967 "#endif\n"
2968 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2969 "uniform sampler Texture_Deluxemap : register(s10),\n"
2970 "#endif\n"
2971 "#ifdef USEREFLECTION\n"
2972 "uniform sampler Texture_Reflection : register(s7),\n"
2973 "#endif\n"
2974 "\n"
2975 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2976 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2977 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2978 "#endif\n"
2979 "#ifdef USEDEFERREDLIGHTMAP\n"
2980 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2981 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2982 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2983 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2984 "#endif\n"
2985 "\n"
2986 "#ifdef USECOLORMAPPING\n"
2987 "uniform half3 Color_Pants : register(c7),\n"
2988 "uniform half3 Color_Shirt : register(c8),\n"
2989 "#endif\n"
2990 "#ifdef USEFOG\n"
2991 "uniform float3 FogColor : register(c16),\n"
2992 "uniform float FogRangeRecip : register(c20),\n"
2993 "uniform float FogPlaneViewDist : register(c19),\n"
2994 "uniform float FogHeightFade : register(c17),\n"
2995 "#endif\n"
2996 "\n"
2997 "#ifdef USEOFFSETMAPPING\n"
2998 "uniform float OffsetMapping_Scale : register(c24),\n"
2999 "#endif\n"
3000 "\n"
3001 "#ifdef USEDEFERREDLIGHTMAP\n"
3002 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3003 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3004 "uniform half3 DeferredMod_Specular : register(c13),\n"
3005 "#endif\n"
3006 "uniform half3 Color_Ambient : register(c3),\n"
3007 "uniform half3 Color_Diffuse : register(c4),\n"
3008 "uniform half3 Color_Specular : register(c5),\n"
3009 "uniform half SpecularPower : register(c36),\n"
3010 "#ifdef USEGLOW\n"
3011 "uniform half3 Color_Glow : register(c6),\n"
3012 "#endif\n"
3013 "uniform half Alpha : register(c0),\n"
3014 "#ifdef USEREFLECTION\n"
3015 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3016 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3017 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3018 "uniform half4 ReflectColor : register(c26),\n"
3019 "#endif\n"
3020 "#ifdef USEREFLECTCUBE\n"
3021 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3022 "uniform sampler Texture_ReflectMask : register(s5),\n"
3023 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3024 "#endif\n"
3025 "#ifdef MODE_LIGHTDIRECTION\n"
3026 "uniform half3 LightColor : register(c21),\n"
3027 "#endif\n"
3028 "#ifdef MODE_LIGHTSOURCE\n"
3029 "uniform half3 LightColor : register(c21),\n"
3030 "#endif\n"
3031 "\n"
3032 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3033 "uniform sampler Texture_Attenuation : register(s9),\n"
3034 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3035 "#endif\n"
3036 "\n"
3037 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3038 "\n"
3039 "#ifdef USESHADOWMAP2D\n"
3040 "# ifdef USESHADOWSAMPLER\n"
3041 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3042 "# else\n"
3043 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3044 "# endif\n"
3045 "#endif\n"
3046 "\n"
3047 "#ifdef USESHADOWMAPVSDCT\n"
3048 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3049 "#endif\n"
3050 "\n"
3051 "#if defined(USESHADOWMAP2D)\n"
3052 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3053 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3054 "#endif\n"
3055 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3056 "\n"
3057 "out float4 gl_FragColor : COLOR\n"
3058 ")\n"
3059 "{\n"
3060 "       float2 TexCoord = TexCoordBoth.xy;\n"
3061 "#ifdef USEVERTEXTEXTUREBLEND\n"
3062 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3063 "#endif\n"
3064 "#ifdef USEOFFSETMAPPING\n"
3065 "       // apply offsetmapping\n"
3066 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3067 "#define TexCoord TexCoordOffset\n"
3068 "#endif\n"
3069 "\n"
3070 "       // combine the diffuse textures (base, pants, shirt)\n"
3071 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3072 "#ifdef USEALPHAKILL\n"
3073 "       if (color.a < 0.5)\n"
3074 "               discard;\n"
3075 "#endif\n"
3076 "       color.a *= Alpha;\n"
3077 "#ifdef USECOLORMAPPING\n"
3078 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3079 "#endif\n"
3080 "#ifdef USEVERTEXTEXTUREBLEND\n"
3081 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3082 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3083 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3084 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3085 "       color.a = 1.0;\n"
3086 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3087 "#endif\n"
3088 "\n"
3089 "       // get the surface normal\n"
3090 "#ifdef USEVERTEXTEXTUREBLEND\n"
3091 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3092 "#else\n"
3093 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3094 "#endif\n"
3095 "\n"
3096 "       // get the material colors\n"
3097 "       half3 diffusetex = color.rgb;\n"
3098 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3099 "# ifdef USEVERTEXTEXTUREBLEND\n"
3100 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3101 "# else\n"
3102 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3103 "# endif\n"
3104 "#endif\n"
3105 "\n"
3106 "#ifdef USEREFLECTCUBE\n"
3107 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3108 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3109 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3110 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3111 "#endif\n"
3112 "\n"
3113 "\n"
3114 "\n"
3115 "\n"
3116 "#ifdef MODE_LIGHTSOURCE\n"
3117 "       // light source\n"
3118 "#ifdef USEDIFFUSE\n"
3119 "       half3 lightnormal = half3(normalize(LightVector));\n"
3120 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3121 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3122 "#ifdef USESPECULAR\n"
3123 "#ifdef USEEXACTSPECULARMATH\n"
3124 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3125 "#else\n"
3126 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3127 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3128 "#endif\n"
3129 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3130 "#endif\n"
3131 "#else\n"
3132 "       color.rgb = diffusetex * Color_Ambient;\n"
3133 "#endif\n"
3134 "       color.rgb *= LightColor;\n"
3135 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3136 "#if defined(USESHADOWMAP2D)\n"
3137 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3138 "#ifdef USESHADOWMAPVSDCT\n"
3139 ", Texture_CubeProjection\n"
3140 "#endif\n"
3141 "       ));\n"
3142 "\n"
3143 "#endif\n"
3144 "# ifdef USECUBEFILTER\n"
3145 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3146 "# endif\n"
3147 "\n"
3148 "#ifdef USESHADOWMAP2D\n"
3149 "#ifdef USESHADOWMAPVSDCT\n"
3150 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3151 "#else\n"
3152 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3153 "#endif\n"
3154 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3155 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3156 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3157 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3158 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3159 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3160 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3161 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3162 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3163 "//     color.r = half(shadowmaptc.z);\n"
3164 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3165 "//     color.r = half(shadowmaptc.z);\n"
3166 "//     color.r = 1;\n"
3167 "//     color.rgb = abs(CubeVector);\n"
3168 "#endif\n"
3169 "//     color.rgb = half3(1,1,1);\n"
3170 "#endif // MODE_LIGHTSOURCE\n"
3171 "\n"
3172 "\n"
3173 "\n"
3174 "\n"
3175 "#ifdef MODE_LIGHTDIRECTION\n"
3176 "#define SHADING\n"
3177 "#ifdef USEDIFFUSE\n"
3178 "       half3 lightnormal = half3(normalize(LightVector));\n"
3179 "#endif\n"
3180 "#define lightcolor LightColor\n"
3181 "#endif // MODE_LIGHTDIRECTION\n"
3182 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3183 "#define SHADING\n"
3184 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3185 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3186 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3187 "       // convert modelspace light vector to tangentspace\n"
3188 "       half3 lightnormal;\n"
3189 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3190 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3191 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3192 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3193 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3194 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3195 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3196 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3197 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3198 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3199 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3200 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3201 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3202 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3203 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3204 "#define SHADING\n"
3205 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3206 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3207 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3208 "#endif\n"
3209 "\n"
3210 "\n"
3211 "\n"
3212 "\n"
3213 "#ifdef MODE_FAKELIGHT\n"
3214 "#define SHADING\n"
3215 "half3 lightnormal = half3(normalize(EyeVector));\n"
3216 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3217 "#endif // MODE_FAKELIGHT\n"
3218 "\n"
3219 "\n"
3220 "\n"
3221 "\n"
3222 "#ifdef MODE_LIGHTMAP\n"
3223 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3224 "#endif // MODE_LIGHTMAP\n"
3225 "#ifdef MODE_VERTEXCOLOR\n"
3226 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3227 "#endif // MODE_VERTEXCOLOR\n"
3228 "#ifdef MODE_FLATCOLOR\n"
3229 "       color.rgb = diffusetex * Color_Ambient;\n"
3230 "#endif // MODE_FLATCOLOR\n"
3231 "\n"
3232 "\n"
3233 "\n"
3234 "\n"
3235 "#ifdef SHADING\n"
3236 "# ifdef USEDIFFUSE\n"
3237 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3238 "#  ifdef USESPECULAR\n"
3239 "#   ifdef USEEXACTSPECULARMATH\n"
3240 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3241 "#   else\n"
3242 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3243 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3244 "#   endif\n"
3245 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3246 "#  else\n"
3247 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3248 "#  endif\n"
3249 "# else\n"
3250 "       color.rgb = diffusetex * Color_Ambient;\n"
3251 "# endif\n"
3252 "#endif\n"
3253 "\n"
3254 "#ifdef USESHADOWMAPORTHO\n"
3255 "       color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3256 "#endif\n"
3257 "\n"
3258 "#ifdef USEDEFERREDLIGHTMAP\n"
3259 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3260 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3261 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3262 "//     color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3263 "//     color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3264 "#endif\n"
3265 "\n"
3266 "#ifdef USEGLOW\n"
3267 "#ifdef USEVERTEXTEXTUREBLEND\n"
3268 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3269 "#else\n"
3270 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3271 "#endif\n"
3272 "#endif\n"
3273 "\n"
3274 "#ifdef USEFOG\n"
3275 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3276 "#endif\n"
3277 "\n"
3278 "       // 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"
3279 "#ifdef USEREFLECTION\n"
3280 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3281 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3282 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3283 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3284 "       // FIXME temporary hack to detect the case that the reflection\n"
3285 "       // gets blackened at edges due to leaving the area that contains actual\n"
3286 "       // content.\n"
3287 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3288 "       // 'appening.\n"
3289 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3290 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3291 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3292 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3293 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3294 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3295 "#endif\n"
3296 "\n"
3297 "       gl_FragColor = float4(color);\n"
3298 "}\n"
3299 "#endif // FRAGMENT_SHADER\n"
3300 "\n"
3301 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3302 "#endif // !MODE_DEFERREDGEOMETRY\n"
3303 "#endif // !MODE_WATER\n"
3304 "#endif // !MODE_REFRACTION\n"
3305 "#endif // !MODE_BLOOMBLUR\n"
3306 "#endif // !MODE_GENERIC\n"
3307 "#endif // !MODE_POSTPROCESS\n"
3308 "#endif // !MODE_SHOWDEPTH\n"
3309 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3310 ;
3311
3312 char *glslshaderstring = NULL;
3313 char *cgshaderstring = NULL;
3314 char *hlslshaderstring = NULL;
3315
3316 //=======================================================================================================================================================
3317
3318 typedef struct shaderpermutationinfo_s
3319 {
3320         const char *pretext;
3321         const char *name;
3322 }
3323 shaderpermutationinfo_t;
3324
3325 typedef struct shadermodeinfo_s
3326 {
3327         const char *vertexfilename;
3328         const char *geometryfilename;
3329         const char *fragmentfilename;
3330         const char *pretext;
3331         const char *name;
3332 }
3333 shadermodeinfo_t;
3334
3335 typedef enum shaderpermutation_e
3336 {
3337         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3338         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3339         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3340         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3341         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3342         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3343         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3344         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3345         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3346         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3347         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3348         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3349         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3350         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3351         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3352         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3353         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3354         SHADERPERMUTATION_SHADOWMAP2D = 1<<17, ///< (lightsource) use shadowmap texture as light filter
3355         SHADERPERMUTATION_SHADOWMAPPCF = 1<<18, ///< (lightsource) use percentage closer filtering on shadowmap test results
3356         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<19, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3357         SHADERPERMUTATION_SHADOWSAMPLER = 1<<20, ///< (lightsource) use hardware shadowmap test
3358         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<21, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3359         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<22, //< (lightsource) use orthographic shadowmap projection
3360         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<23, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3361         SHADERPERMUTATION_ALPHAKILL = 1<<24, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3362         SHADERPERMUTATION_REFLECTCUBE = 1<<25, ///< fake reflections using global cubemap (not HDRI light probe)
3363         SHADERPERMUTATION_NORMALMAPSCROLLBLEND = 1<<26, // (water) counter-direction normalmaps scrolling
3364         SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array
3365         SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3366 }
3367 shaderpermutation_t;
3368
3369 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3370 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3371 {
3372         {"#define USEDIFFUSE\n", " diffuse"},
3373         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3374         {"#define USEVIEWTINT\n", " viewtint"},
3375         {"#define USECOLORMAPPING\n", " colormapping"},
3376         {"#define USESATURATION\n", " saturation"},
3377         {"#define USEFOGINSIDE\n", " foginside"},
3378         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3379         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3380         {"#define USEGAMMARAMPS\n", " gammaramps"},
3381         {"#define USECUBEFILTER\n", " cubefilter"},
3382         {"#define USEGLOW\n", " glow"},
3383         {"#define USEBLOOM\n", " bloom"},
3384         {"#define USESPECULAR\n", " specular"},
3385         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3386         {"#define USEREFLECTION\n", " reflection"},
3387         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3388         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3389         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3390         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3391         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3392         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3393         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3394         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3395         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3396         {"#define USEALPHAKILL\n", " alphakill"},
3397         {"#define USEREFLECTCUBE\n", " reflectcube"},
3398         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3399 };
3400
3401 // this enum selects which of the glslshadermodeinfo entries should be used
3402 typedef enum shadermode_e
3403 {
3404         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3405         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3406         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3407         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3408         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3409         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3410         SHADERMODE_FAKELIGHT, ///< (fakelight) modulate texture by "fake" lighting (no lightmaps, no nothing)
3411         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3412         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3413         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3414         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3415         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3416         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3417         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3418         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3419         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3420         SHADERMODE_COUNT
3421 }
3422 shadermode_t;
3423
3424 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3425 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3426 {
3427         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3428         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3429         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3430         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3431         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3432         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3433         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3434         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3435         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3436         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3437         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3438         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3439         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3440         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3441         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3442         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3443 };
3444
3445 #ifdef SUPPORTCG
3446 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3447 {
3448         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3449         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3450         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3451         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3452         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3453         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3454         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
3455         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3456         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3457         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3458         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3459         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3460         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3461         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3462         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3463         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3464 };
3465 #endif
3466
3467 #ifdef SUPPORTD3D
3468 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3469 {
3470         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3471         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3472         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3473         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3474         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3475         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3476         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3477         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3478         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3479         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3480         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3481         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3482         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3483         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3484         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3485         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3486 };
3487 #endif
3488
3489 struct r_glsl_permutation_s;
3490 typedef struct r_glsl_permutation_s
3491 {
3492         /// hash lookup data
3493         struct r_glsl_permutation_s *hashnext;
3494         unsigned int mode;
3495         unsigned int permutation;
3496
3497         /// indicates if we have tried compiling this permutation already
3498         qboolean compiled;
3499         /// 0 if compilation failed
3500         int program;
3501         /// locations of detected uniforms in program object, or -1 if not found
3502         int loc_Texture_First;
3503         int loc_Texture_Second;
3504         int loc_Texture_GammaRamps;
3505         int loc_Texture_Normal;
3506         int loc_Texture_Color;
3507         int loc_Texture_Gloss;
3508         int loc_Texture_Glow;
3509         int loc_Texture_SecondaryNormal;
3510         int loc_Texture_SecondaryColor;
3511         int loc_Texture_SecondaryGloss;
3512         int loc_Texture_SecondaryGlow;
3513         int loc_Texture_Pants;
3514         int loc_Texture_Shirt;
3515         int loc_Texture_FogHeightTexture;
3516         int loc_Texture_FogMask;
3517         int loc_Texture_Lightmap;
3518         int loc_Texture_Deluxemap;
3519         int loc_Texture_Attenuation;
3520         int loc_Texture_Cube;
3521         int loc_Texture_Refraction;
3522         int loc_Texture_Reflection;
3523         int loc_Texture_ShadowMap2D;
3524         int loc_Texture_CubeProjection;
3525         int loc_Texture_ScreenDepth;
3526         int loc_Texture_ScreenNormalMap;
3527         int loc_Texture_ScreenDiffuse;
3528         int loc_Texture_ScreenSpecular;
3529         int loc_Texture_ReflectMask;
3530         int loc_Texture_ReflectCube;
3531         int loc_Alpha;
3532         int loc_BloomBlur_Parameters;
3533         int loc_ClientTime;
3534         int loc_Color_Ambient;
3535         int loc_Color_Diffuse;
3536         int loc_Color_Specular;
3537         int loc_Color_Glow;
3538         int loc_Color_Pants;
3539         int loc_Color_Shirt;
3540         int loc_DeferredColor_Ambient;
3541         int loc_DeferredColor_Diffuse;
3542         int loc_DeferredColor_Specular;
3543         int loc_DeferredMod_Diffuse;
3544         int loc_DeferredMod_Specular;
3545         int loc_DistortScaleRefractReflect;
3546         int loc_EyePosition;
3547         int loc_FogColor;
3548         int loc_FogHeightFade;
3549         int loc_FogPlane;
3550         int loc_FogPlaneViewDist;
3551         int loc_FogRangeRecip;
3552         int loc_LightColor;
3553         int loc_LightDir;
3554         int loc_LightPosition;
3555         int loc_OffsetMapping_Scale;
3556         int loc_PixelSize;
3557         int loc_ReflectColor;
3558         int loc_ReflectFactor;
3559         int loc_ReflectOffset;
3560         int loc_RefractColor;
3561         int loc_Saturation;
3562         int loc_ScreenCenterRefractReflect;
3563         int loc_ScreenScaleRefractReflect;
3564         int loc_ScreenToDepth;
3565         int loc_ShadowMap_Parameters;
3566         int loc_ShadowMap_TextureScale;
3567         int loc_SpecularPower;
3568         int loc_UserVec1;
3569         int loc_UserVec2;
3570         int loc_UserVec3;
3571         int loc_UserVec4;
3572         int loc_ViewTintColor;
3573         int loc_ViewToLight;
3574         int loc_ModelToLight;
3575         int loc_TexMatrix;
3576         int loc_BackgroundTexMatrix;
3577         int loc_ModelViewProjectionMatrix;
3578         int loc_ModelViewMatrix;
3579         int loc_PixelToScreenTexCoord;
3580         int loc_ModelToReflectCube;
3581         int loc_ShadowMapMatrix;
3582         int loc_BloomColorSubtract;
3583         int loc_NormalmapScrollBlend;
3584 }
3585 r_glsl_permutation_t;
3586
3587 #define SHADERPERMUTATION_HASHSIZE 256
3588
3589
3590 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3591 // these can NOT degrade! only use for simple stuff
3592 enum
3593 {
3594         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3595         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3596         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3597         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3598         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3599         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
3600 };
3601 #define SHADERSTATICPARMS_COUNT 6
3602
3603 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3604 static int shaderstaticparms_count = 0;
3605
3606 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3607 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3608 qboolean R_CompileShader_CheckStaticParms(void)
3609 {
3610         static int r_compileshader_staticparms_save[1];
3611         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3612         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3613
3614         // detect all
3615         if (r_glsl_saturation_redcompensate.integer)
3616                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3617         if (r_shadow_glossexact.integer)
3618                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3619         if (r_glsl_postprocess.integer)
3620         {
3621                 if (r_glsl_postprocess_uservec1_enable.integer)
3622                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3623                 if (r_glsl_postprocess_uservec2_enable.integer)
3624                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3625                 if (r_glsl_postprocess_uservec3_enable.integer)
3626                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3627                 if (r_glsl_postprocess_uservec4_enable.integer)
3628                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3629         }
3630         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3631 }
3632
3633 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3634         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3635                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3636         else \
3637                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3638 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3639 {
3640         shaderstaticparms_count = 0;
3641
3642         // emit all
3643         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3644         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3645         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3646         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3647         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3648         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3649 }
3650
3651 /// information about each possible shader permutation
3652 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3653 /// currently selected permutation
3654 r_glsl_permutation_t *r_glsl_permutation;
3655 /// storage for permutations linked in the hash table
3656 memexpandablearray_t r_glsl_permutationarray;
3657
3658 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3659 {
3660         //unsigned int hashdepth = 0;
3661         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3662         r_glsl_permutation_t *p;
3663         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3664         {
3665                 if (p->mode == mode && p->permutation == permutation)
3666                 {
3667                         //if (hashdepth > 10)
3668                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3669                         return p;
3670                 }
3671                 //hashdepth++;
3672         }
3673         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3674         p->mode = mode;
3675         p->permutation = permutation;
3676         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3677         r_glsl_permutationhash[mode][hashindex] = p;
3678         //if (hashdepth > 10)
3679         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3680         return p;
3681 }
3682
3683 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3684 {
3685         char *shaderstring;
3686         if (!filename || !filename[0])
3687                 return NULL;
3688         if (!strcmp(filename, "glsl/default.glsl"))
3689         {
3690                 if (!glslshaderstring)
3691                 {
3692                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3693                         if (glslshaderstring)
3694                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3695                         else
3696                                 glslshaderstring = (char *)builtinshaderstring;
3697                 }
3698                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3699                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3700                 return shaderstring;
3701         }
3702         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3703         if (shaderstring)
3704         {
3705                 if (printfromdisknotice)
3706                         Con_DPrintf("from disk %s... ", filename);
3707                 return shaderstring;
3708         }
3709         return shaderstring;
3710 }
3711
3712 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3713 {
3714         int i;
3715         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3716         char *vertexstring, *geometrystring, *fragmentstring;
3717         char permutationname[256];
3718         int vertstrings_count = 0;
3719         int geomstrings_count = 0;
3720         int fragstrings_count = 0;
3721         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3722         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3723         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3724
3725         if (p->compiled)
3726                 return;
3727         p->compiled = true;
3728         p->program = 0;
3729
3730         permutationname[0] = 0;
3731         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3732         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3733         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3734
3735         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3736
3737         // the first pretext is which type of shader to compile as
3738         // (later these will all be bound together as a program object)
3739         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3740         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3741         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3742
3743         // the second pretext is the mode (for example a light source)
3744         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3745         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3746         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3747         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3748
3749         // now add all the permutation pretexts
3750         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3751         {
3752                 if (permutation & (1<<i))
3753                 {
3754                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3755                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3756                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3757                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3758                 }
3759                 else
3760                 {
3761                         // keep line numbers correct
3762                         vertstrings_list[vertstrings_count++] = "\n";
3763                         geomstrings_list[geomstrings_count++] = "\n";
3764                         fragstrings_list[fragstrings_count++] = "\n";
3765                 }
3766         }
3767
3768         // add static parms
3769         R_CompileShader_AddStaticParms(mode, permutation);
3770         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3771         vertstrings_count += shaderstaticparms_count;
3772         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3773         geomstrings_count += shaderstaticparms_count;
3774         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3775         fragstrings_count += shaderstaticparms_count;
3776
3777         // now append the shader text itself
3778         vertstrings_list[vertstrings_count++] = vertexstring;
3779         geomstrings_list[geomstrings_count++] = geometrystring;
3780         fragstrings_list[fragstrings_count++] = fragmentstring;
3781
3782         // if any sources were NULL, clear the respective list
3783         if (!vertexstring)
3784                 vertstrings_count = 0;
3785         if (!geometrystring)
3786                 geomstrings_count = 0;
3787         if (!fragmentstring)
3788                 fragstrings_count = 0;
3789
3790         // compile the shader program
3791         if (vertstrings_count + geomstrings_count + fragstrings_count)
3792                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3793         if (p->program)
3794         {
3795                 CHECKGLERROR
3796                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3797                 // look up all the uniform variable names we care about, so we don't
3798                 // have to look them up every time we set them
3799
3800                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3801                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3802                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3803                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3804                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3805                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3806                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3807                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3808                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3809                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3810                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3811                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3812                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3813                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3814                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3815                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3816                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3817                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3818                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3819                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3820                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3821                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3822                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3823                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3824                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3825                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3826                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3827                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3828                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3829                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3830                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3831                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3832                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3833                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3834                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3835                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3836                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3837                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3838                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3839                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3840                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3841                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3842                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3843                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3844                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3845                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3846                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3847                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3848                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3849                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3850                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3851                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3852                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3853                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3854                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3855                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3856                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3857                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3858                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3859                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3860                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3861                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3862                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3863                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3864                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3865                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3866                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3867                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3868                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3869                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3870                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3871                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3872                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3873                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3874                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3875                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3876                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3877                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3878                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3879                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3880                 p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3881                 p->loc_NormalmapScrollBlend       = qglGetUniformLocationARB(p->program, "NormalmapScrollBlend");
3882                 // initialize the samplers to refer to the texture units we use
3883                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3884                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3885                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3886                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3887                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3888                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3889                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3890                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3891                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3892                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3893                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3894                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3895                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3896                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3897                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3898                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3899                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3900                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3901                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3902                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3903                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3904                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3905                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3906                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3907                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3908                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3909                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3910                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3911                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3912                 CHECKGLERROR
3913                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3914         }
3915         else
3916                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3917
3918         // free the strings
3919         if (vertexstring)
3920                 Mem_Free(vertexstring);
3921         if (geometrystring)
3922                 Mem_Free(geometrystring);
3923         if (fragmentstring)
3924                 Mem_Free(fragmentstring);
3925 }
3926
3927 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3928 {
3929         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3930         if (r_glsl_permutation != perm)
3931         {
3932                 r_glsl_permutation = perm;
3933                 if (!r_glsl_permutation->program)
3934                 {
3935                         if (!r_glsl_permutation->compiled)
3936                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3937                         if (!r_glsl_permutation->program)
3938                         {
3939                                 // remove features until we find a valid permutation
3940                                 int i;
3941                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3942                                 {
3943                                         // reduce i more quickly whenever it would not remove any bits
3944                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3945                                         if (!(permutation & j))
3946                                                 continue;
3947                                         permutation -= j;
3948                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3949                                         if (!r_glsl_permutation->compiled)
3950                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3951                                         if (r_glsl_permutation->program)
3952                                                 break;
3953                                 }
3954                                 if (i >= SHADERPERMUTATION_COUNT)
3955                                 {
3956                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3957                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3958                                         qglUseProgramObjectARB(0);CHECKGLERROR
3959                                         return; // no bit left to clear, entire mode is broken
3960                                 }
3961                         }
3962                 }
3963                 CHECKGLERROR
3964                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3965         }
3966         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3967         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3968         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3969 }
3970
3971 #ifdef SUPPORTCG
3972 #include <Cg/cgGL.h>
3973 struct r_cg_permutation_s;
3974 typedef struct r_cg_permutation_s
3975 {
3976         /// hash lookup data
3977         struct r_cg_permutation_s *hashnext;
3978         unsigned int mode;
3979         unsigned int permutation;
3980
3981         /// indicates if we have tried compiling this permutation already
3982         qboolean compiled;
3983         /// 0 if compilation failed
3984         CGprogram vprogram;
3985         CGprogram fprogram;
3986         /// locations of detected parameters in programs, or NULL if not found
3987         CGparameter vp_EyePosition;
3988         CGparameter vp_FogPlane;
3989         CGparameter vp_LightDir;
3990         CGparameter vp_LightPosition;
3991         CGparameter vp_ModelToLight;
3992         CGparameter vp_TexMatrix;
3993         CGparameter vp_BackgroundTexMatrix;
3994         CGparameter vp_ModelViewProjectionMatrix;
3995         CGparameter vp_ModelViewMatrix;
3996         CGparameter vp_ShadowMapMatrix;
3997
3998         CGparameter fp_Texture_First;
3999         CGparameter fp_Texture_Second;
4000         CGparameter fp_Texture_GammaRamps;
4001         CGparameter fp_Texture_Normal;
4002         CGparameter fp_Texture_Color;
4003         CGparameter fp_Texture_Gloss;
4004         CGparameter fp_Texture_Glow;
4005         CGparameter fp_Texture_SecondaryNormal;
4006         CGparameter fp_Texture_SecondaryColor;
4007         CGparameter fp_Texture_SecondaryGloss;
4008         CGparameter fp_Texture_SecondaryGlow;
4009         CGparameter fp_Texture_Pants;
4010         CGparameter fp_Texture_Shirt;
4011         CGparameter fp_Texture_FogHeightTexture;
4012         CGparameter fp_Texture_FogMask;
4013         CGparameter fp_Texture_Lightmap;
4014         CGparameter fp_Texture_Deluxemap;
4015         CGparameter fp_Texture_Attenuation;
4016         CGparameter fp_Texture_Cube;
4017         CGparameter fp_Texture_Refraction;
4018         CGparameter fp_Texture_Reflection;
4019         CGparameter fp_Texture_ShadowMap2D;
4020         CGparameter fp_Texture_CubeProjection;
4021         CGparameter fp_Texture_ScreenDepth;
4022         CGparameter fp_Texture_ScreenNormalMap;
4023         CGparameter fp_Texture_ScreenDiffuse;
4024         CGparameter fp_Texture_ScreenSpecular;
4025         CGparameter fp_Texture_ReflectMask;
4026         CGparameter fp_Texture_ReflectCube;
4027         CGparameter fp_Alpha;
4028         CGparameter fp_BloomBlur_Parameters;
4029         CGparameter fp_ClientTime;
4030         CGparameter fp_Color_Ambient;
4031         CGparameter fp_Color_Diffuse;
4032         CGparameter fp_Color_Specular;
4033         CGparameter fp_Color_Glow;
4034         CGparameter fp_Color_Pants;
4035         CGparameter fp_Color_Shirt;
4036         CGparameter fp_DeferredColor_Ambient;
4037         CGparameter fp_DeferredColor_Diffuse;
4038         CGparameter fp_DeferredColor_Specular;
4039         CGparameter fp_DeferredMod_Diffuse;
4040         CGparameter fp_DeferredMod_Specular;
4041         CGparameter fp_DistortScaleRefractReflect;
4042         CGparameter fp_EyePosition;
4043         CGparameter fp_FogColor;
4044         CGparameter fp_FogHeightFade;
4045         CGparameter fp_FogPlane;
4046         CGparameter fp_FogPlaneViewDist;
4047         CGparameter fp_FogRangeRecip;
4048         CGparameter fp_LightColor;
4049         CGparameter fp_LightDir;
4050         CGparameter fp_LightPosition;
4051         CGparameter fp_OffsetMapping_Scale;
4052         CGparameter fp_PixelSize;
4053         CGparameter fp_ReflectColor;
4054         CGparameter fp_ReflectFactor;
4055         CGparameter fp_ReflectOffset;
4056         CGparameter fp_RefractColor;
4057         CGparameter fp_Saturation;
4058         CGparameter fp_ScreenCenterRefractReflect;
4059         CGparameter fp_ScreenScaleRefractReflect;
4060         CGparameter fp_ScreenToDepth;
4061         CGparameter fp_ShadowMap_Parameters;
4062         CGparameter fp_ShadowMap_TextureScale;
4063         CGparameter fp_SpecularPower;
4064         CGparameter fp_UserVec1;
4065         CGparameter fp_UserVec2;
4066         CGparameter fp_UserVec3;
4067         CGparameter fp_UserVec4;
4068         CGparameter fp_ViewTintColor;
4069         CGparameter fp_ViewToLight;
4070         CGparameter fp_PixelToScreenTexCoord;
4071         CGparameter fp_ModelToReflectCube;
4072         CGparameter fp_BloomColorSubtract;
4073         CGparameter fp_NormalmapScrollBlend;
4074 }
4075 r_cg_permutation_t;
4076
4077 /// information about each possible shader permutation
4078 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4079 /// currently selected permutation
4080 r_cg_permutation_t *r_cg_permutation;
4081 /// storage for permutations linked in the hash table
4082 memexpandablearray_t r_cg_permutationarray;
4083
4084 #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));}}
4085
4086 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4087 {
4088         //unsigned int hashdepth = 0;
4089         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4090         r_cg_permutation_t *p;
4091         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4092         {
4093                 if (p->mode == mode && p->permutation == permutation)
4094                 {
4095                         //if (hashdepth > 10)
4096                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4097                         return p;
4098                 }
4099                 //hashdepth++;
4100         }
4101         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4102         p->mode = mode;
4103         p->permutation = permutation;
4104         p->hashnext = r_cg_permutationhash[mode][hashindex];
4105         r_cg_permutationhash[mode][hashindex] = p;
4106         //if (hashdepth > 10)
4107         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4108         return p;
4109 }
4110
4111 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4112 {
4113         char *shaderstring;
4114         if (!filename || !filename[0])
4115                 return NULL;
4116         if (!strcmp(filename, "cg/default.cg"))
4117         {
4118                 if (!cgshaderstring)
4119                 {
4120                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4121                         if (cgshaderstring)
4122                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4123                         else
4124                                 cgshaderstring = (char *)builtincgshaderstring;
4125                 }
4126                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4127                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4128                 return shaderstring;
4129         }
4130         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4131         if (shaderstring)
4132         {
4133                 if (printfromdisknotice)
4134                         Con_DPrintf("from disk %s... ", filename);
4135                 return shaderstring;
4136         }
4137         return shaderstring;
4138 }
4139
4140 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4141 {
4142         // TODO: load or create .fp and .vp shader files
4143 }
4144
4145 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4146 {
4147         int i;
4148         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4149         int vertstring_length = 0;
4150         int geomstring_length = 0;
4151         int fragstring_length = 0;
4152         char *t;
4153         char *vertexstring, *geometrystring, *fragmentstring;
4154         char *vertstring, *geomstring, *fragstring;
4155         char permutationname[256];
4156         char cachename[256];
4157         CGprofile vertexProfile;
4158         CGprofile fragmentProfile;
4159         int vertstrings_count = 0;
4160         int geomstrings_count = 0;
4161         int fragstrings_count = 0;
4162         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4163         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4164         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4165
4166         if (p->compiled)
4167                 return;
4168         p->compiled = true;
4169         p->vprogram = NULL;
4170         p->fprogram = NULL;
4171
4172         permutationname[0] = 0;
4173         cachename[0] = 0;
4174         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4175         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4176         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4177
4178         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4179         strlcat(cachename, "cg/", sizeof(cachename));
4180
4181         // the first pretext is which type of shader to compile as
4182         // (later these will all be bound together as a program object)
4183         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4184         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4185         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4186
4187         // the second pretext is the mode (for example a light source)
4188         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4189         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4190         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4191         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4192         strlcat(cachename, modeinfo->name, sizeof(cachename));
4193
4194         // now add all the permutation pretexts
4195         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4196         {
4197                 if (permutation & (1<<i))
4198                 {
4199                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4200                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4201                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4202                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4203                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4204                 }
4205                 else
4206                 {
4207                         // keep line numbers correct
4208                         vertstrings_list[vertstrings_count++] = "\n";
4209                         geomstrings_list[geomstrings_count++] = "\n";
4210                         fragstrings_list[fragstrings_count++] = "\n";
4211                 }
4212         }
4213
4214         // add static parms
4215         R_CompileShader_AddStaticParms(mode, permutation);
4216         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4217         vertstrings_count += shaderstaticparms_count;
4218         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4219         geomstrings_count += shaderstaticparms_count;
4220         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4221         fragstrings_count += shaderstaticparms_count;
4222
4223         // replace spaces in the cachename with _ characters
4224         for (i = 0;cachename[i];i++)
4225                 if (cachename[i] == ' ')
4226                         cachename[i] = '_';
4227
4228         // now append the shader text itself
4229         vertstrings_list[vertstrings_count++] = vertexstring;
4230         geomstrings_list[geomstrings_count++] = geometrystring;
4231         fragstrings_list[fragstrings_count++] = fragmentstring;
4232
4233         // if any sources were NULL, clear the respective list
4234         if (!vertexstring)
4235                 vertstrings_count = 0;
4236         if (!geometrystring)
4237                 geomstrings_count = 0;
4238         if (!fragmentstring)
4239                 fragstrings_count = 0;
4240
4241         vertstring_length = 0;
4242         for (i = 0;i < vertstrings_count;i++)
4243                 vertstring_length += strlen(vertstrings_list[i]);
4244         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4245         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4246                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4247
4248         geomstring_length = 0;
4249         for (i = 0;i < geomstrings_count;i++)
4250                 geomstring_length += strlen(geomstrings_list[i]);
4251         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4252         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4253                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4254
4255         fragstring_length = 0;
4256         for (i = 0;i < fragstrings_count;i++)
4257                 fragstring_length += strlen(fragstrings_list[i]);
4258         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4259         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4260                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4261
4262         CHECKGLERROR
4263         CHECKCGERROR
4264         //vertexProfile = CG_PROFILE_ARBVP1;
4265         //fragmentProfile = CG_PROFILE_ARBFP1;
4266         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4267         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4268         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4269         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4270         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4271         CHECKGLERROR
4272
4273         // try to load the cached shader, or generate one
4274         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4275
4276         // if caching failed, do a dynamic compile for now
4277         CHECKCGERROR
4278         if (vertstring[0] && !p->vprogram)
4279                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4280         CHECKCGERROR
4281         if (fragstring[0] && !p->fprogram)
4282                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4283         CHECKCGERROR
4284
4285         // look up all the uniform variable names we care about, so we don't
4286         // have to look them up every time we set them
4287         if (p->vprogram)
4288         {
4289                 CHECKCGERROR
4290                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4291                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4292                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4293                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4294                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4295                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4296                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4297                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4298                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4299                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4300                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4301                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4302                 CHECKCGERROR
4303         }
4304         if (p->fprogram)
4305         {
4306                 CHECKCGERROR
4307                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4308                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4309                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4310                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4311                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4312                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4313                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4314                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4315                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4316                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4317                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4318                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4319                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4320                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4321                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4322                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4323                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4324                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4325                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4326                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4327                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4328                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4329                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4330                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4331                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4332                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4333                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4334                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4335                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4336                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4337                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4338                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4339                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4340                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4341                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4342                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4343                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4344                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4345                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4346                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4347                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4348                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4349                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4350                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4351                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4352                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4353                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4354                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4355                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4356                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4357                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4358                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4359                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4360                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4361                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4362                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4363                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4364                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4365                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4366                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4367                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4368                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4369                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4370                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4371                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4372                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4373                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4374                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4375                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4376                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4377                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4378                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4379                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4380                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4381                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4382                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4383                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4384                 p->fp_NormalmapScrollBlend       = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4385                 CHECKCGERROR
4386         }
4387
4388         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4389                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4390         else
4391                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4392
4393         // free the strings
4394         if (vertstring)
4395                 Mem_Free(vertstring);
4396         if (geomstring)
4397                 Mem_Free(geomstring);
4398         if (fragstring)
4399                 Mem_Free(fragstring);
4400         if (vertexstring)
4401                 Mem_Free(vertexstring);
4402         if (geometrystring)
4403                 Mem_Free(geometrystring);
4404         if (fragmentstring)
4405                 Mem_Free(fragmentstring);
4406 }
4407
4408 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4409 {
4410         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4411         CHECKGLERROR
4412         CHECKCGERROR
4413         if (r_cg_permutation != perm)
4414         {
4415                 r_cg_permutation = perm;
4416                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4417                 {
4418                         if (!r_cg_permutation->compiled)
4419                                 R_CG_CompilePermutation(perm, mode, permutation);
4420                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4421                         {
4422                                 // remove features until we find a valid permutation
4423                                 int i;
4424                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4425                                 {
4426                                         // reduce i more quickly whenever it would not remove any bits
4427                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4428                                         if (!(permutation & j))
4429                                                 continue;
4430                                         permutation -= j;
4431                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4432                                         if (!r_cg_permutation->compiled)
4433                                                 R_CG_CompilePermutation(perm, mode, permutation);
4434                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4435                                                 break;
4436                                 }
4437                                 if (i >= SHADERPERMUTATION_COUNT)
4438                                 {
4439                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4440                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4441                                         return; // no bit left to clear, entire mode is broken
4442                                 }
4443                         }
4444                 }
4445                 CHECKGLERROR
4446                 CHECKCGERROR
4447                 if (r_cg_permutation->vprogram)
4448                 {
4449                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4450                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4451                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4452                 }
4453                 else
4454                 {
4455                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4456                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4457                 }
4458                 if (r_cg_permutation->fprogram)
4459                 {
4460                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4461                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4462                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4463                 }
4464                 else
4465                 {
4466                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4467                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4468                 }
4469         }
4470         CHECKCGERROR
4471         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4472         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4473         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4474 }
4475
4476 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4477 {
4478         cgGLSetTextureParameter(param, R_GetTexture(tex));
4479         cgGLEnableTextureParameter(param);
4480 }
4481 #endif
4482
4483 #ifdef SUPPORTD3D
4484
4485 #ifdef SUPPORTD3D
4486 #include <d3d9.h>
4487 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4488 extern D3DCAPS9 vid_d3d9caps;
4489 #endif
4490
4491 struct r_hlsl_permutation_s;
4492 typedef struct r_hlsl_permutation_s
4493 {
4494         /// hash lookup data
4495         struct r_hlsl_permutation_s *hashnext;
4496         unsigned int mode;
4497         unsigned int permutation;
4498
4499         /// indicates if we have tried compiling this permutation already
4500         qboolean compiled;
4501         /// NULL if compilation failed
4502         IDirect3DVertexShader9 *vertexshader;
4503         IDirect3DPixelShader9 *pixelshader;
4504 }
4505 r_hlsl_permutation_t;
4506
4507 typedef enum D3DVSREGISTER_e
4508 {
4509         D3DVSREGISTER_TexMatrix = 0, // float4x4
4510         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4511         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4512         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4513         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4514         D3DVSREGISTER_ModelToLight = 20, // float4x4
4515         D3DVSREGISTER_EyePosition = 24,
4516         D3DVSREGISTER_FogPlane = 25,
4517         D3DVSREGISTER_LightDir = 26,
4518         D3DVSREGISTER_LightPosition = 27,
4519 }
4520 D3DVSREGISTER_t;
4521
4522 typedef enum D3DPSREGISTER_e
4523 {
4524         D3DPSREGISTER_Alpha = 0,
4525         D3DPSREGISTER_BloomBlur_Parameters = 1,
4526         D3DPSREGISTER_ClientTime = 2,
4527         D3DPSREGISTER_Color_Ambient = 3,
4528         D3DPSREGISTER_Color_Diffuse = 4,
4529         D3DPSREGISTER_Color_Specular = 5,
4530         D3DPSREGISTER_Color_Glow = 6,
4531         D3DPSREGISTER_Color_Pants = 7,
4532         D3DPSREGISTER_Color_Shirt = 8,
4533         D3DPSREGISTER_DeferredColor_Ambient = 9,
4534         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4535         D3DPSREGISTER_DeferredColor_Specular = 11,
4536         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4537         D3DPSREGISTER_DeferredMod_Specular = 13,
4538         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4539         D3DPSREGISTER_EyePosition = 15, // unused
4540         D3DPSREGISTER_FogColor = 16,
4541         D3DPSREGISTER_FogHeightFade = 17,
4542         D3DPSREGISTER_FogPlane = 18,
4543         D3DPSREGISTER_FogPlaneViewDist = 19,
4544         D3DPSREGISTER_FogRangeRecip = 20,
4545         D3DPSREGISTER_LightColor = 21,
4546         D3DPSREGISTER_LightDir = 22, // unused
4547         D3DPSREGISTER_LightPosition = 23,
4548         D3DPSREGISTER_OffsetMapping_Scale = 24,
4549         D3DPSREGISTER_PixelSize = 25,
4550         D3DPSREGISTER_ReflectColor = 26,
4551         D3DPSREGISTER_ReflectFactor = 27,
4552         D3DPSREGISTER_ReflectOffset = 28,
4553         D3DPSREGISTER_RefractColor = 29,
4554         D3DPSREGISTER_Saturation = 30,
4555         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4556         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4557         D3DPSREGISTER_ScreenToDepth = 33,
4558         D3DPSREGISTER_ShadowMap_Parameters = 34,
4559         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4560         D3DPSREGISTER_SpecularPower = 36,
4561         D3DPSREGISTER_UserVec1 = 37,
4562         D3DPSREGISTER_UserVec2 = 38,
4563         D3DPSREGISTER_UserVec3 = 39,
4564         D3DPSREGISTER_UserVec4 = 40,
4565         D3DPSREGISTER_ViewTintColor = 41,
4566         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4567         D3DPSREGISTER_BloomColorSubtract = 43,
4568         D3DPSREGISTER_ViewToLight = 44, // float4x4
4569         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4570         D3DPSREGISTER_NormalmapScrollBlend = 52,
4571         // next at 53
4572 }
4573 D3DPSREGISTER_t;
4574
4575 /// information about each possible shader permutation
4576 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4577 /// currently selected permutation
4578 r_hlsl_permutation_t *r_hlsl_permutation;
4579 /// storage for permutations linked in the hash table
4580 memexpandablearray_t r_hlsl_permutationarray;
4581
4582 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4583 {
4584         //unsigned int hashdepth = 0;
4585         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4586         r_hlsl_permutation_t *p;
4587         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4588         {
4589                 if (p->mode == mode && p->permutation == permutation)
4590                 {
4591                         //if (hashdepth > 10)
4592                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4593                         return p;
4594                 }
4595                 //hashdepth++;
4596         }
4597         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4598         p->mode = mode;
4599         p->permutation = permutation;
4600         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4601         r_hlsl_permutationhash[mode][hashindex] = p;
4602         //if (hashdepth > 10)
4603         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4604         return p;
4605 }
4606
4607 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4608 {
4609         char *shaderstring;
4610         if (!filename || !filename[0])
4611                 return NULL;
4612         if (!strcmp(filename, "hlsl/default.hlsl"))
4613         {
4614                 if (!hlslshaderstring)
4615                 {
4616                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4617                         if (hlslshaderstring)
4618                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4619                         else
4620                                 hlslshaderstring = (char *)builtincgshaderstring;
4621                 }
4622                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4623                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4624                 return shaderstring;
4625         }
4626         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4627         if (shaderstring)
4628         {
4629                 if (printfromdisknotice)
4630                         Con_DPrintf("from disk %s... ", filename);
4631                 return shaderstring;
4632         }
4633         return shaderstring;
4634 }
4635
4636 #include <d3dx9.h>
4637 //#include <d3dx9shader.h>
4638 //#include <d3dx9mesh.h>
4639
4640 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4641 {
4642         DWORD *vsbin = NULL;
4643         DWORD *psbin = NULL;
4644         fs_offset_t vsbinsize;
4645         fs_offset_t psbinsize;
4646 //      IDirect3DVertexShader9 *vs = NULL;
4647 //      IDirect3DPixelShader9 *ps = NULL;
4648         ID3DXBuffer *vslog = NULL;
4649         ID3DXBuffer *vsbuffer = NULL;
4650         ID3DXConstantTable *vsconstanttable = NULL;
4651         ID3DXBuffer *pslog = NULL;
4652         ID3DXBuffer *psbuffer = NULL;
4653         ID3DXConstantTable *psconstanttable = NULL;
4654         int vsresult = 0;
4655         int psresult = 0;
4656         char temp[MAX_INPUTLINE];
4657         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4658         qboolean debugshader = gl_paranoid.integer != 0;
4659         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4660         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4661         if (!debugshader)
4662         {
4663                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4664                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4665         }
4666         if ((!vsbin && vertstring) || (!psbin && fragstring))
4667         {
4668                 const char* dllnames_d3dx9 [] =
4669                 {
4670                         "d3dx9_43.dll",
4671                         "d3dx9_42.dll",
4672                         "d3dx9_41.dll",
4673                         "d3dx9_40.dll",
4674                         "d3dx9_39.dll",
4675                         "d3dx9_38.dll",
4676                         "d3dx9_37.dll",
4677                         "d3dx9_36.dll",
4678                         "d3dx9_35.dll",
4679                         "d3dx9_34.dll",
4680                         "d3dx9_33.dll",
4681                         "d3dx9_32.dll",
4682                         "d3dx9_31.dll",
4683                         "d3dx9_30.dll",
4684                         "d3dx9_29.dll",
4685                         "d3dx9_28.dll",
4686                         "d3dx9_27.dll",
4687                         "d3dx9_26.dll",
4688                         "d3dx9_25.dll",
4689                         "d3dx9_24.dll",
4690                         NULL
4691                 };
4692                 dllhandle_t d3dx9_dll = NULL;
4693                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4694                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4695                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4696                 dllfunction_t d3dx9_dllfuncs[] =
4697                 {
4698                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4699                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4700                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4701                         {NULL, NULL}
4702                 };
4703                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4704                 {
4705                         DWORD shaderflags = 0;
4706                         if (debugshader)
4707                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4708                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4709                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4710                         if (vertstring && vertstring[0])
4711                         {
4712                                 if (debugshader)
4713                                 {
4714 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4715 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4716                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4717                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4718                                 }
4719                                 else
4720                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4721                                 if (vsbuffer)
4722                                 {
4723                                         vsbinsize = vsbuffer->GetBufferSize();
4724                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4725                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4726                                         vsbuffer->Release();
4727                                 }
4728                                 if (vslog)
4729                                 {
4730                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4731                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4732                                         vslog->Release();
4733                                 }
4734                         }
4735                         if (fragstring && fragstring[0])
4736                         {
4737                                 if (debugshader)
4738                                 {
4739 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4740 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4741                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4742                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4743                                 }
4744                                 else
4745                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4746                                 if (psbuffer)
4747                                 {
4748                                         psbinsize = psbuffer->GetBufferSize();
4749                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4750                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4751                                         psbuffer->Release();
4752                                 }
4753                                 if (pslog)
4754                                 {
4755                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4756                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4757                                         pslog->Release();
4758                                 }
4759                         }
4760                         Sys_UnloadLibrary(&d3dx9_dll);
4761                 }
4762                 else
4763                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4764         }
4765         if (vsbin && psbin)
4766         {
4767                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4768                 if (FAILED(vsresult))
4769                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4770                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4771                 if (FAILED(psresult))
4772                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4773         }
4774         // free the shader data
4775         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4776         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4777 }
4778
4779 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4780 {
4781         int i;
4782         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4783         int vertstring_length = 0;
4784         int geomstring_length = 0;
4785         int fragstring_length = 0;
4786         char *t;
4787         char *vertexstring, *geometrystring, *fragmentstring;
4788         char *vertstring, *geomstring, *fragstring;
4789         char permutationname[256];
4790         char cachename[256];
4791         int vertstrings_count = 0;
4792         int geomstrings_count = 0;
4793         int fragstrings_count = 0;
4794         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4795         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4796         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4797
4798         if (p->compiled)
4799                 return;
4800         p->compiled = true;
4801         p->vertexshader = NULL;
4802         p->pixelshader = NULL;
4803
4804         permutationname[0] = 0;
4805         cachename[0] = 0;
4806         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4807         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4808         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4809
4810         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4811         strlcat(cachename, "hlsl/", sizeof(cachename));
4812
4813         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4814         vertstrings_count = 0;
4815         geomstrings_count = 0;
4816         fragstrings_count = 0;
4817         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4818         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4819         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4820
4821         // the first pretext is which type of shader to compile as
4822         // (later these will all be bound together as a program object)
4823         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4824         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4825         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4826
4827         // the second pretext is the mode (for example a light source)
4828         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4829         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4830         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4831         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4832         strlcat(cachename, modeinfo->name, sizeof(cachename));
4833
4834         // now add all the permutation pretexts
4835         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4836         {
4837                 if (permutation & (1<<i))
4838                 {
4839                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4840                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4841                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4842                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4843                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4844                 }
4845                 else
4846                 {
4847                         // keep line numbers correct
4848                         vertstrings_list[vertstrings_count++] = "\n";
4849                         geomstrings_list[geomstrings_count++] = "\n";
4850                         fragstrings_list[fragstrings_count++] = "\n";
4851                 }
4852         }
4853
4854         // add static parms
4855         R_CompileShader_AddStaticParms(mode, permutation);
4856         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4857         vertstrings_count += shaderstaticparms_count;
4858         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4859         geomstrings_count += shaderstaticparms_count;
4860         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4861         fragstrings_count += shaderstaticparms_count;
4862
4863         // replace spaces in the cachename with _ characters
4864         for (i = 0;cachename[i];i++)
4865                 if (cachename[i] == ' ')
4866                         cachename[i] = '_';
4867
4868         // now append the shader text itself
4869         vertstrings_list[vertstrings_count++] = vertexstring;
4870         geomstrings_list[geomstrings_count++] = geometrystring;
4871         fragstrings_list[fragstrings_count++] = fragmentstring;
4872
4873         // if any sources were NULL, clear the respective list
4874         if (!vertexstring)
4875                 vertstrings_count = 0;
4876         if (!geometrystring)
4877                 geomstrings_count = 0;
4878         if (!fragmentstring)
4879                 fragstrings_count = 0;
4880
4881         vertstring_length = 0;
4882         for (i = 0;i < vertstrings_count;i++)
4883                 vertstring_length += strlen(vertstrings_list[i]);
4884         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4885         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4886                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4887
4888         geomstring_length = 0;
4889         for (i = 0;i < geomstrings_count;i++)
4890                 geomstring_length += strlen(geomstrings_list[i]);
4891         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4892         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4893                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4894
4895         fragstring_length = 0;
4896         for (i = 0;i < fragstrings_count;i++)
4897                 fragstring_length += strlen(fragstrings_list[i]);
4898         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4899         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4900                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4901
4902         // try to load the cached shader, or generate one
4903         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4904
4905         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4906                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4907         else
4908                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4909
4910         // free the strings
4911         if (vertstring)
4912                 Mem_Free(vertstring);
4913         if (geomstring)
4914                 Mem_Free(geomstring);
4915         if (fragstring)
4916                 Mem_Free(fragstring);
4917         if (vertexstring)
4918                 Mem_Free(vertexstring);
4919         if (geometrystring)
4920                 Mem_Free(geometrystring);
4921         if (fragmentstring)
4922                 Mem_Free(fragmentstring);
4923 }
4924
4925 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4926 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4927 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);}
4928 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);}
4929 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);}
4930 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);}
4931
4932 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4933 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4934 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);}
4935 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);}
4936 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);}
4937 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);}
4938
4939 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4940 {
4941         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4942         if (r_hlsl_permutation != perm)
4943         {
4944                 r_hlsl_permutation = perm;
4945                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4946                 {
4947                         if (!r_hlsl_permutation->compiled)
4948                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4949                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4950                         {
4951                                 // remove features until we find a valid permutation
4952                                 int i;
4953                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4954                                 {
4955                                         // reduce i more quickly whenever it would not remove any bits
4956                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4957                                         if (!(permutation & j))
4958                                                 continue;
4959                                         permutation -= j;
4960                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4961                                         if (!r_hlsl_permutation->compiled)
4962                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4963                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4964                                                 break;
4965                                 }
4966                                 if (i >= SHADERPERMUTATION_COUNT)
4967                                 {
4968                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4969                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4970                                         return; // no bit left to clear, entire mode is broken
4971                                 }
4972                         }
4973                 }
4974                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4975                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4976         }
4977         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4978         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4979         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4980 }
4981 #endif
4982
4983 void R_GLSL_Restart_f(void)
4984 {
4985         unsigned int i, limit;
4986         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4987                 Mem_Free(glslshaderstring);
4988         glslshaderstring = NULL;
4989         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4990                 Mem_Free(cgshaderstring);
4991         cgshaderstring = NULL;
4992         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4993                 Mem_Free(hlslshaderstring);
4994         hlslshaderstring = NULL;
4995         switch(vid.renderpath)
4996         {
4997         case RENDERPATH_D3D9:
4998 #ifdef SUPPORTD3D
4999                 {
5000                         r_hlsl_permutation_t *p;
5001                         r_hlsl_permutation = NULL;
5002 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5003 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5004 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5005 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5006                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
5007                         for (i = 0;i < limit;i++)
5008                         {
5009                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
5010                                 {
5011                                         if (p->vertexshader)
5012                                                 IDirect3DVertexShader9_Release(p->vertexshader);
5013                                         if (p->pixelshader)
5014                                                 IDirect3DPixelShader9_Release(p->pixelshader);
5015                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
5016                                 }
5017                         }
5018                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
5019                 }
5020 #endif
5021                 break;
5022         case RENDERPATH_D3D10:
5023                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5024                 break;
5025         case RENDERPATH_D3D11:
5026                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5027                 break;
5028         case RENDERPATH_GL20:
5029                 {
5030                         r_glsl_permutation_t *p;
5031                         r_glsl_permutation = NULL;
5032                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
5033                         for (i = 0;i < limit;i++)
5034                         {
5035                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
5036                                 {
5037                                         GL_Backend_FreeProgram(p->program);
5038                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5039                                 }
5040                         }
5041                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5042                 }
5043                 break;
5044         case RENDERPATH_CGGL:
5045 #ifdef SUPPORTCG
5046                 {
5047                         r_cg_permutation_t *p;
5048                         r_cg_permutation = NULL;
5049                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5050                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5051                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5052                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5053                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5054                         for (i = 0;i < limit;i++)
5055                         {
5056                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5057                                 {
5058                                         if (p->vprogram)
5059                                                 cgDestroyProgram(p->vprogram);
5060                                         if (p->fprogram)
5061                                                 cgDestroyProgram(p->fprogram);
5062                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5063                                 }
5064                         }
5065                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5066                 }
5067 #endif
5068                 break;
5069         case RENDERPATH_GL13:
5070         case RENDERPATH_GL11:
5071                 break;
5072         }
5073 }
5074
5075 void R_GLSL_DumpShader_f(void)
5076 {
5077         int i;
5078         qfile_t *file;
5079
5080         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5081         if (file)
5082         {
5083                 FS_Print(file, "/* The engine may define the following macros:\n");
5084                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5085                 for (i = 0;i < SHADERMODE_COUNT;i++)
5086                         FS_Print(file, glslshadermodeinfo[i].pretext);
5087                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5088                         FS_Print(file, shaderpermutationinfo[i].pretext);
5089                 FS_Print(file, "*/\n");
5090                 FS_Print(file, builtinshaderstring);
5091                 FS_Close(file);
5092                 Con_Printf("glsl/default.glsl written\n");
5093         }
5094         else
5095                 Con_Printf("failed to write to glsl/default.glsl\n");
5096
5097 #ifdef SUPPORTCG
5098         file = FS_OpenRealFile("cg/default.cg", "w", false);
5099         if (file)
5100         {
5101                 FS_Print(file, "/* The engine may define the following macros:\n");
5102                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5103                 for (i = 0;i < SHADERMODE_COUNT;i++)
5104                         FS_Print(file, cgshadermodeinfo[i].pretext);
5105                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5106                         FS_Print(file, shaderpermutationinfo[i].pretext);
5107                 FS_Print(file, "*/\n");
5108                 FS_Print(file, builtincgshaderstring);
5109                 FS_Close(file);
5110                 Con_Printf("cg/default.cg written\n");
5111         }
5112         else
5113                 Con_Printf("failed to write to cg/default.cg\n");
5114 #endif
5115
5116 #ifdef SUPPORTD3D
5117         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5118         if (file)
5119         {
5120                 FS_Print(file, "/* The engine may define the following macros:\n");
5121                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5122                 for (i = 0;i < SHADERMODE_COUNT;i++)
5123                         FS_Print(file, hlslshadermodeinfo[i].pretext);
5124                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5125                         FS_Print(file, shaderpermutationinfo[i].pretext);
5126                 FS_Print(file, "*/\n");
5127                 FS_Print(file, builtincgshaderstring);
5128                 FS_Close(file);
5129                 Con_Printf("hlsl/default.hlsl written\n");
5130         }
5131         else
5132                 Con_Printf("failed to write to hlsl/default.hlsl\n");
5133 #endif
5134 }
5135
5136 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5137 {
5138         if (!second)
5139                 texturemode = GL_MODULATE;
5140         switch (vid.renderpath)
5141         {
5142         case RENDERPATH_D3D9:
5143 #ifdef SUPPORTD3D
5144                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5145                 R_Mesh_TexBind(GL20TU_FIRST , first );
5146                 R_Mesh_TexBind(GL20TU_SECOND, second);
5147 #endif
5148                 break;
5149         case RENDERPATH_D3D10:
5150                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5151                 break;
5152         case RENDERPATH_D3D11:
5153                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5154                 break;
5155         case RENDERPATH_GL20:
5156                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5157                 R_Mesh_TexBind(GL20TU_FIRST , first );
5158                 R_Mesh_TexBind(GL20TU_SECOND, second);
5159                 break;
5160         case RENDERPATH_CGGL:
5161 #ifdef SUPPORTCG
5162                 CHECKCGERROR
5163                 R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
5164                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5165                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5166 #endif
5167                 break;
5168         case RENDERPATH_GL13:
5169                 R_Mesh_TexBind(0, first );
5170                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5171                 R_Mesh_TexBind(1, second);
5172                 if (second)
5173                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5174                 break;
5175         case RENDERPATH_GL11:
5176                 R_Mesh_TexBind(0, first );
5177                 break;
5178         }
5179 }
5180
5181 void R_SetupShader_DepthOrShadow(void)
5182 {
5183         switch (vid.renderpath)
5184         {
5185         case RENDERPATH_D3D9:
5186 #ifdef SUPPORTD3D
5187                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5188 #endif
5189                 break;
5190         case RENDERPATH_D3D10:
5191                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5192                 break;
5193         case RENDERPATH_D3D11:
5194                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5195                 break;
5196         case RENDERPATH_GL20:
5197                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5198                 break;
5199         case RENDERPATH_CGGL:
5200 #ifdef SUPPORTCG
5201                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5202 #endif
5203                 break;
5204         case RENDERPATH_GL13:
5205                 R_Mesh_TexBind(0, 0);
5206                 R_Mesh_TexBind(1, 0);
5207                 break;
5208         case RENDERPATH_GL11:
5209                 R_Mesh_TexBind(0, 0);
5210                 break;
5211         }
5212 }
5213
5214 void R_SetupShader_ShowDepth(void)
5215 {
5216         switch (vid.renderpath)
5217         {
5218         case RENDERPATH_D3D9:
5219 #ifdef SUPPORTHLSL
5220                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5221 #endif
5222                 break;
5223         case RENDERPATH_D3D10:
5224                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5225                 break;
5226         case RENDERPATH_D3D11:
5227                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5228                 break;
5229         case RENDERPATH_GL20:
5230                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5231                 break;
5232         case RENDERPATH_CGGL:
5233 #ifdef SUPPORTCG
5234                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5235 #endif
5236                 break;
5237         case RENDERPATH_GL13:
5238                 break;
5239         case RENDERPATH_GL11:
5240                 break;
5241         }
5242 }
5243
5244 extern qboolean r_shadow_usingdeferredprepass;
5245 extern cvar_t r_shadow_deferred_8bitrange;
5246 extern rtexture_t *r_shadow_attenuationgradienttexture;
5247 extern rtexture_t *r_shadow_attenuation2dtexture;
5248 extern rtexture_t *r_shadow_attenuation3dtexture;
5249 extern qboolean r_shadow_usingshadowmap2d;
5250 extern qboolean r_shadow_usingshadowmaportho;
5251 extern float r_shadow_shadowmap_texturescale[2];
5252 extern float r_shadow_shadowmap_parameters[4];
5253 extern qboolean r_shadow_shadowmapvsdct;
5254 extern qboolean r_shadow_shadowmapsampler;
5255 extern int r_shadow_shadowmappcf;
5256 extern rtexture_t *r_shadow_shadowmap2dtexture;
5257 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5258 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5259 extern matrix4x4_t r_shadow_shadowmapmatrix;
5260 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5261 extern int r_shadow_prepass_width;
5262 extern int r_shadow_prepass_height;
5263 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5264 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5265 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5266 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5267 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5268 extern cvar_t gl_mesh_separatearrays;
5269 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5270 {
5271         // a blendfunc allows colormod if:
5272         // a) it can never keep the destination pixel invariant, or
5273         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5274         // this is to prevent unintended side effects from colormod
5275
5276         // in formulas:
5277         // IF there is a (s, sa) for which for all (d, da),
5278         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5279         // THEN, for this (s, sa) and all (colormod, d, da):
5280         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5281         // OBVIOUSLY, this means that
5282         //   s*colormod * src(s*colormod, d, sa, da) = 0
5283         //   dst(s*colormod, d, sa, da)              = 1
5284
5285         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5286
5287         // main condition to leave dst color invariant:
5288         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5289         //   src == GL_ZERO:
5290         //     s * 0 + d * dst(s, d, sa, da) == d
5291         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5292         //       => colormod is a problem for GL_SRC_COLOR only
5293         //   src == GL_ONE:
5294         //     s + d * dst(s, d, sa, da) == d
5295         //       => s == 0
5296         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5297         //       => colormod is never problematic for these
5298         //   src == GL_SRC_COLOR:
5299         //     s*s + d * dst(s, d, sa, da) == d
5300         //       => s == 0
5301         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5302         //       => colormod is never problematic for these
5303         //   src == GL_ONE_MINUS_SRC_COLOR:
5304         //     s*(1-s) + d * dst(s, d, sa, da) == d
5305         //       => s == 0 or s == 1
5306         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5307         //       => colormod is a problem for GL_SRC_COLOR only
5308         //   src == GL_DST_COLOR
5309         //     s*d + d * dst(s, d, sa, da) == d
5310         //       => s == 1
5311         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5312         //       => colormod is always a problem
5313         //     or
5314         //       => s == 0
5315         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5316         //       => colormod is never problematic for these
5317         //       => BUT, we do not know s! We must assume it is problematic
5318         //       then... except in GL_ONE case, where we know all invariant
5319         //       cases are fine
5320         //   src == GL_ONE_MINUS_DST_COLOR
5321         //     s*(1-d) + d * dst(s, d, sa, da) == d
5322         //       => s == 0 (1-d is impossible to handle for our desired result)
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         //   src == GL_SRC_ALPHA
5326         //     s*sa + d * dst(s, d, sa, da) == d
5327         //       => s == 0, or sa == 0
5328         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5329         //       => colormod breaks in the case GL_SRC_COLOR only
5330         //   src == GL_ONE_MINUS_SRC_ALPHA
5331         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5332         //       => s == 0, or sa == 1
5333         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5334         //       => colormod breaks in the case GL_SRC_COLOR only
5335         //   src == GL_DST_ALPHA
5336         //     s*da + d * dst(s, d, sa, da) == d
5337         //       => s == 0
5338         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5339         //       => colormod is never problematic for these
5340
5341         switch(src)
5342         {
5343                 case GL_ZERO:
5344                 case GL_ONE_MINUS_SRC_COLOR:
5345                 case GL_SRC_ALPHA:
5346                 case GL_ONE_MINUS_SRC_ALPHA:
5347                         if(dst == GL_SRC_COLOR)
5348                                 return false;
5349                         return true;
5350                 case GL_ONE:
5351                 case GL_SRC_COLOR:
5352                 case GL_ONE_MINUS_DST_COLOR:
5353                 case GL_DST_ALPHA:
5354                 case GL_ONE_MINUS_DST_ALPHA:
5355                         return true;
5356                 case GL_DST_COLOR:
5357                         if(dst == GL_ONE)
5358                                 return true;
5359                         return false;
5360                 default:
5361                         return false;
5362         }
5363 }
5364 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)
5365 {
5366         // select a permutation of the lighting shader appropriate to this
5367         // combination of texture, entity, light source, and fogging, only use the
5368         // minimum features necessary to avoid wasting rendering time in the
5369         // fragment shader on features that are not being used
5370         unsigned int permutation = 0;
5371         unsigned int mode = 0;
5372         qboolean allow_colormod;
5373         static float dummy_colormod[3] = {1, 1, 1};
5374         float *colormod = rsurface.colormod;
5375         float m16f[16];
5376         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5377         if (rsurfacepass == RSURFPASS_BACKGROUND)
5378         {
5379                 // distorted background
5380                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5381                 {
5382                         mode = SHADERMODE_WATER;
5383                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
5384                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
5385                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5386                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5387                 }
5388                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5389                 {
5390                         mode = SHADERMODE_REFRACTION;
5391                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5392                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5393                 }
5394                 else
5395                 {
5396                         mode = SHADERMODE_GENERIC;
5397                         permutation |= SHADERPERMUTATION_DIFFUSE;
5398                         GL_BlendFunc(GL_ONE, GL_ZERO);
5399                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5400                 }
5401                 GL_AlphaTest(false);
5402         }
5403         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5404         {
5405                 if (r_glsl_offsetmapping.integer)
5406                 {
5407                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5408                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5409                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5410                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5411                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5412                         {
5413                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5414                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5415                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5416                         }
5417                 }
5418                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5419                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5420                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5421                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5422                 // normalmap (deferred prepass), may use alpha test on diffuse
5423                 mode = SHADERMODE_DEFERREDGEOMETRY;
5424                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5425                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5426                 GL_AlphaTest(false);
5427                 GL_BlendFunc(GL_ONE, GL_ZERO);
5428                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5429         }
5430         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5431         {
5432                 if (r_glsl_offsetmapping.integer)
5433                 {
5434                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5435                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5436                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5437                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5438                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5439                         {
5440                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5441                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5442                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5443                         }
5444                 }
5445                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5446                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5447                 // light source
5448                 mode = SHADERMODE_LIGHTSOURCE;
5449                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5450                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5451                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5452                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5453                 if (diffusescale > 0)
5454                         permutation |= SHADERPERMUTATION_DIFFUSE;
5455                 if (specularscale > 0)
5456                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5457                 if (r_refdef.fogenabled)
5458                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5459                 if (rsurface.texture->colormapping)
5460                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5461                 if (r_shadow_usingshadowmap2d)
5462                 {
5463                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5464                         if(r_shadow_shadowmapvsdct)
5465                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5466
5467                         if (r_shadow_shadowmapsampler)
5468                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5469                         if (r_shadow_shadowmappcf > 1)
5470                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5471                         else if (r_shadow_shadowmappcf)
5472                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5473                 }
5474                 if (rsurface.texture->reflectmasktexture)
5475                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5476                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5477                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5478                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5479         }
5480         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5481         {
5482                 if (r_glsl_offsetmapping.integer)
5483                 {
5484                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5485                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5486                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5487                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5488                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5489                         {
5490                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5491                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5492                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5493                         }
5494                 }
5495                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5496                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5497                 // unshaded geometry (fullbright or ambient model lighting)
5498                 mode = SHADERMODE_FLATCOLOR;
5499                 ambientscale = diffusescale = specularscale = 0;
5500                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5501                         permutation |= SHADERPERMUTATION_GLOW;
5502                 if (r_refdef.fogenabled)
5503                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5504                 if (rsurface.texture->colormapping)
5505                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5506                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5507                 {
5508                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5509                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5510
5511                         if (r_shadow_shadowmapsampler)
5512                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5513                         if (r_shadow_shadowmappcf > 1)
5514                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5515                         else if (r_shadow_shadowmappcf)
5516                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5517                 }
5518                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5519                         permutation |= SHADERPERMUTATION_REFLECTION;
5520                 if (rsurface.texture->reflectmasktexture)
5521                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5522                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5523                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5524                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5525         }
5526         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5527         {
5528                 if (r_glsl_offsetmapping.integer)
5529                 {
5530                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5531                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5532                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5533                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5534                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5535                         {
5536                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5537                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5538                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5539                         }
5540                 }
5541                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5542                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5543                 // directional model lighting
5544                 mode = SHADERMODE_LIGHTDIRECTION;
5545                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5546                         permutation |= SHADERPERMUTATION_GLOW;
5547                 permutation |= SHADERPERMUTATION_DIFFUSE;
5548                 if (specularscale > 0)
5549                         permutation |= SHADERPERMUTATION_SPECULAR;
5550                 if (r_refdef.fogenabled)
5551                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5552                 if (rsurface.texture->colormapping)
5553                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5554                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5555                 {
5556                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5557                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5558
5559                         if (r_shadow_shadowmapsampler)
5560                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5561                         if (r_shadow_shadowmappcf > 1)
5562                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5563                         else if (r_shadow_shadowmappcf)
5564                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5565                 }
5566                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5567                         permutation |= SHADERPERMUTATION_REFLECTION;
5568                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5569                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5570                 if (rsurface.texture->reflectmasktexture)
5571                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5572                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5573                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5574                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5575         }
5576         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5577         {
5578                 if (r_glsl_offsetmapping.integer)
5579                 {
5580                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5581                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5582                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5583                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5584                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5585                         {
5586                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5587                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5588                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5589                         }
5590                 }
5591                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5592                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5593                 // ambient model lighting
5594                 mode = SHADERMODE_LIGHTDIRECTION;
5595                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5596                         permutation |= SHADERPERMUTATION_GLOW;
5597                 if (r_refdef.fogenabled)
5598                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5599                 if (rsurface.texture->colormapping)
5600                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5601                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5602                 {
5603                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5604                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5605
5606                         if (r_shadow_shadowmapsampler)
5607                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5608                         if (r_shadow_shadowmappcf > 1)
5609                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5610                         else if (r_shadow_shadowmappcf)
5611                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5612                 }
5613                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5614                         permutation |= SHADERPERMUTATION_REFLECTION;
5615                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5616                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5617                 if (rsurface.texture->reflectmasktexture)
5618                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5619                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5620                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5621                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5622         }
5623         else
5624         {
5625                 if (r_glsl_offsetmapping.integer)
5626                 {
5627                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5628                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5629                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5630                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5631                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5632                         {
5633                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5634                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5635                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5636                         }
5637                 }
5638                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5639                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5640                 // lightmapped wall
5641                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5642                         permutation |= SHADERPERMUTATION_GLOW;
5643                 if (r_refdef.fogenabled)
5644                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5645                 if (rsurface.texture->colormapping)
5646                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5647                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5648                 {
5649                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5650                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5651
5652                         if (r_shadow_shadowmapsampler)
5653                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5654                         if (r_shadow_shadowmappcf > 1)
5655                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5656                         else if (r_shadow_shadowmappcf)
5657                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5658                 }
5659                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5660                         permutation |= SHADERPERMUTATION_REFLECTION;
5661                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5662                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5663                 if (rsurface.texture->reflectmasktexture)
5664                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5665                 if (FAKELIGHT_ENABLED)
5666                 {
5667                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5668                         mode = SHADERMODE_FAKELIGHT;
5669                         permutation |= SHADERPERMUTATION_DIFFUSE;
5670                         if (specularscale > 0)
5671                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5672                 }
5673                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5674                 {
5675                         // deluxemapping (light direction texture)
5676                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5677                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5678                         else
5679                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5680                         permutation |= SHADERPERMUTATION_DIFFUSE;
5681                         if (specularscale > 0)
5682                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5683                 }
5684                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5685                 {
5686                         // fake deluxemapping (uniform light direction in tangentspace)
5687                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5688                         permutation |= SHADERPERMUTATION_DIFFUSE;
5689                         if (specularscale > 0)
5690                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5691                 }
5692                 else if (rsurface.uselightmaptexture)
5693                 {
5694                         // ordinary lightmapping (q1bsp, q3bsp)
5695                         mode = SHADERMODE_LIGHTMAP;
5696                 }
5697                 else
5698                 {
5699                         // ordinary vertex coloring (q3bsp)
5700                         mode = SHADERMODE_VERTEXCOLOR;
5701                 }
5702                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5703                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5704                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5705         }
5706         if(!allow_colormod)
5707                 colormod = dummy_colormod;
5708         switch(vid.renderpath)
5709         {
5710         case RENDERPATH_D3D9:
5711 #ifdef SUPPORTD3D
5712                 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);
5713                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5714                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5715                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5716                 if (mode == SHADERMODE_LIGHTSOURCE)
5717                 {
5718                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5719                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5720                 }
5721                 else
5722                 {
5723                         if (mode == SHADERMODE_LIGHTDIRECTION)                                   
5724                         {
5725                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5726                         }
5727                 }
5728                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5729                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5730                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5731                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5732                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5733
5734                 if (mode == SHADERMODE_LIGHTSOURCE)
5735                 {
5736                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5737                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5738                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5739                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5740                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5741
5742                         // additive passes are only darkened by fog, not tinted
5743                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5744                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5745                 }
5746                 else
5747                 {
5748                         if (mode == SHADERMODE_FLATCOLOR)
5749                         {
5750                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5751                         }
5752                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5753                         {
5754                                 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]);
5755                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5756                                 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);
5757                                 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);
5758                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5759                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5760                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5761                         }
5762                         else
5763                         {
5764                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5765                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5766                                 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);
5767                                 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);
5768                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5769                         }
5770                         // additive passes are only darkened by fog, not tinted
5771                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5772                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5773                         else
5774                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5775                         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);
5776                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5777                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5778                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5779                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5780                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5781                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5782                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5783                         if (mode == SHADERMODE_WATER)
5784                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5785                 }
5786                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5787                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5788                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5789                 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));
5790                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5791                 if (rsurface.texture->pantstexture)
5792                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5793                 else
5794                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5795                 if (rsurface.texture->shirttexture)
5796                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5797                 else
5798                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5799                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5800                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5801                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5802                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5803                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5804                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5805                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5806
5807                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5808                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5809                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5810                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5811                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5812                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5813                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5814                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5815                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5816                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5817                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5818                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5819                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5820                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5821                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5822                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5823                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5824                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5825                 {
5826                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5827                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5828                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5829                 }
5830                 else
5831                 {
5832                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5833                 }
5834 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5835 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5836                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5837                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5838                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5839                 {
5840                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5841                         if (rsurface.rtlight)
5842                         {
5843                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5844                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5845                         }
5846                 }
5847 #endif
5848                 break;
5849         case RENDERPATH_D3D10:
5850                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5851                 break;
5852         case RENDERPATH_D3D11:
5853                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5854                 break;
5855         case RENDERPATH_GL20:
5856                 if (gl_mesh_separatearrays.integer)
5857                 {
5858                         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);
5859                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5860                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5861                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5862                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5863                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5864                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5865                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5866                 }
5867                 else
5868                 {
5869                         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);
5870                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5871                 }
5872                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5873                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5874                 if (mode == SHADERMODE_LIGHTSOURCE)
5875                 {
5876                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5877                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5878                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5879                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5880                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5881                         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);
5882         
5883                         // additive passes are only darkened by fog, not tinted
5884                         if (r_glsl_permutation->loc_FogColor >= 0)
5885                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5886                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5887                 }
5888                 else
5889                 {
5890                         if (mode == SHADERMODE_FLATCOLOR)
5891                         {
5892                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5893                         }
5894                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5895                         {
5896                                 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]);
5897                                 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]);
5898                                 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);
5899                                 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);
5900                                 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);
5901                                 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]);
5902                                 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]);
5903                         }
5904                         else
5905                         {
5906                                 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]);
5907                                 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]);
5908                                 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);
5909                                 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);
5910                                 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);
5911                         }
5912                         // additive passes are only darkened by fog, not tinted
5913                         if (r_glsl_permutation->loc_FogColor >= 0)
5914                         {
5915                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5916                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5917                                 else
5918                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5919                         }
5920                         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);
5921                         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]);
5922                         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]);
5923                         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]);
5924                         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]);
5925                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5926                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5927                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5928                         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]);
5929                 }
5930                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5931                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5932                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5933                 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]);
5934                 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]);
5935
5936                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5937                 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));
5938                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5939                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5940                 {
5941                         if (rsurface.texture->pantstexture)
5942                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5943                         else
5944                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5945                 }
5946                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5947                 {
5948                         if (rsurface.texture->shirttexture)
5949                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5950                         else
5951                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5952                 }
5953                 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]);
5954                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5955                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5956                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5957                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5958                 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]);
5959                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5960
5961         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5962         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5963         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5964                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5965                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5966                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5967                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5968                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5969                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5970                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5971                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5972                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5973                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5974                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5975                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5976                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5977                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5978                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5979                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5980                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5981                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5982                 {
5983                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5984                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5985                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5986                 }
5987                 else
5988                 {
5989                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5990                 }
5991 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5992 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5993                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5994                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5995                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5996                 {
5997                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5998                         if (rsurface.rtlight)
5999                         {
6000                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
6001                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
6002                         }
6003                 }
6004                 CHECKGLERROR
6005                 break;
6006         case RENDERPATH_CGGL:
6007 #ifdef SUPPORTCG
6008                 if (gl_mesh_separatearrays.integer)
6009                 {
6010                         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);
6011                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
6012                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
6013                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
6014                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
6015                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6016                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6017                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6018                 }
6019                 else
6020                 {
6021                         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);
6022                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6023                 }
6024                 R_SetupShader_SetPermutationCG(mode, permutation);
6025                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6026                 if (mode == SHADERMODE_LIGHTSOURCE)
6027                 {
6028                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6029                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6030                 }
6031                 else
6032                 {
6033                         if (mode == SHADERMODE_LIGHTDIRECTION)
6034                         {
6035                                 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
6036                         }
6037                 }
6038                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6039                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6040                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6041                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6042                 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
6043                 CHECKGLERROR
6044
6045                 if (mode == SHADERMODE_LIGHTSOURCE)
6046                 {
6047                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6048                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6049                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6050                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6051                         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
6052
6053                         // additive passes are only darkened by fog, not tinted
6054                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6055                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6056                 }
6057                 else
6058                 {
6059                         if (mode == SHADERMODE_FLATCOLOR)
6060                         {
6061                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6062                         }
6063                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6064                         {
6065                                 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
6066                                 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
6067                                 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
6068                                 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
6069                                 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
6070                                 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
6071                                 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
6072                         }
6073                         else
6074                         {
6075                                 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
6076                                 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
6077                                 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
6078                                 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
6079                                 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
6080                         }
6081                         // additive passes are only darkened by fog, not tinted
6082                         if (r_cg_permutation->fp_FogColor)
6083                         {
6084                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6085                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6086                                 else
6087                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6088                                 CHECKCGERROR
6089                         }
6090                         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
6091                         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
6092                         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
6093                         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
6094                         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
6095                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6096                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6097                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6098                         if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6099                 }
6100                 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
6101                 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
6102                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6103                 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
6104                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6105                 if (r_cg_permutation->fp_Color_Pants)
6106                 {
6107                         if (rsurface.texture->pantstexture)
6108                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6109                         else
6110                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6111                         CHECKCGERROR
6112                 }
6113                 if (r_cg_permutation->fp_Color_Shirt)
6114                 {
6115                         if (rsurface.texture->shirttexture)
6116                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6117                         else
6118                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6119                         CHECKCGERROR
6120                 }
6121                 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
6122                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6123                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6124                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6125                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6126                 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
6127                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6128
6129         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
6130         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
6131         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
6132                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
6133                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
6134                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
6135                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
6136                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
6137                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
6138                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
6139                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
6140                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
6141                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
6142                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
6143                 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
6144                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
6145                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
6146                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6147                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6148                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6149                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6150                 {
6151                         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
6152                         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
6153                         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
6154                 }
6155                 else
6156                 {
6157                         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
6158                 }
6159                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6160                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6161                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
6162                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
6163                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6164                 {
6165                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6166                         if (rsurface.rtlight)
6167                         {
6168                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6169                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6170                         }
6171                 }
6172
6173                 CHECKGLERROR
6174 #endif
6175                 break;
6176         case RENDERPATH_GL13:
6177         case RENDERPATH_GL11:
6178                 break;
6179         }
6180 }
6181
6182 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6183 {
6184         // select a permutation of the lighting shader appropriate to this
6185         // combination of texture, entity, light source, and fogging, only use the
6186         // minimum features necessary to avoid wasting rendering time in the
6187         // fragment shader on features that are not being used
6188         unsigned int permutation = 0;
6189         unsigned int mode = 0;
6190         const float *lightcolorbase = rtlight->currentcolor;
6191         float ambientscale = rtlight->ambientscale;
6192         float diffusescale = rtlight->diffusescale;
6193         float specularscale = rtlight->specularscale;
6194         // this is the location of the light in view space
6195         vec3_t viewlightorigin;
6196         // this transforms from view space (camera) to light space (cubemap)
6197         matrix4x4_t viewtolight;
6198         matrix4x4_t lighttoview;
6199         float viewtolight16f[16];
6200         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6201         // light source
6202         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6203         if (rtlight->currentcubemap != r_texture_whitecube)
6204                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6205         if (diffusescale > 0)
6206                 permutation |= SHADERPERMUTATION_DIFFUSE;
6207         if (specularscale > 0)
6208                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6209         if (r_shadow_usingshadowmap2d)
6210         {
6211                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6212                 if (r_shadow_shadowmapvsdct)
6213                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6214
6215                 if (r_shadow_shadowmapsampler)
6216                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6217                 if (r_shadow_shadowmappcf > 1)
6218                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6219                 else if (r_shadow_shadowmappcf)
6220                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6221         }
6222         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6223         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6224         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6225         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6226         switch(vid.renderpath)
6227         {
6228         case RENDERPATH_D3D9:
6229 #ifdef SUPPORTD3D
6230                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6231                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6232                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6233                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6234                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6235                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6236                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6237                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6238                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6239                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6240                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6241
6242                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6243                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
6244                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6245                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6246                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
6247                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6248 #endif
6249                 break;
6250         case RENDERPATH_D3D10:
6251                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6252                 break;
6253         case RENDERPATH_D3D11:
6254                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6255                 break;
6256         case RENDERPATH_GL20:
6257                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6258                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6259                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6260                 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);
6261                 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);
6262                 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);
6263                 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]);
6264                 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]);
6265                 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));
6266                 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]);
6267                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6268
6269                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6270                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6271                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6272                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6273                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6274                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6275                 break;
6276         case RENDERPATH_CGGL:
6277 #ifdef SUPPORTCG
6278                 R_SetupShader_SetPermutationCG(mode, permutation);
6279                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6280                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6281                 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
6282                 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
6283                 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
6284                 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
6285                 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
6286                 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
6287                 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
6288                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6289
6290                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6291                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6292                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6293                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6294                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6295                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6296 #endif
6297                 break;
6298         case RENDERPATH_GL13:
6299         case RENDERPATH_GL11:
6300                 break;
6301         }
6302 }
6303
6304 #define SKINFRAME_HASH 1024
6305
6306 typedef struct
6307 {
6308         int loadsequence; // incremented each level change
6309         memexpandablearray_t array;
6310         skinframe_t *hash[SKINFRAME_HASH];
6311 }
6312 r_skinframe_t;
6313 r_skinframe_t r_skinframe;
6314
6315 void R_SkinFrame_PrepareForPurge(void)
6316 {
6317         r_skinframe.loadsequence++;
6318         // wrap it without hitting zero
6319         if (r_skinframe.loadsequence >= 200)
6320                 r_skinframe.loadsequence = 1;
6321 }
6322
6323 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6324 {
6325         if (!skinframe)
6326                 return;
6327         // mark the skinframe as used for the purging code
6328         skinframe->loadsequence = r_skinframe.loadsequence;
6329 }
6330
6331 void R_SkinFrame_Purge(void)
6332 {
6333         int i;
6334         skinframe_t *s;
6335         for (i = 0;i < SKINFRAME_HASH;i++)
6336         {
6337                 for (s = r_skinframe.hash[i];s;s = s->next)
6338                 {
6339                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6340                         {
6341                                 if (s->merged == s->base)
6342                                         s->merged = NULL;
6343                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6344                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6345                                 R_PurgeTexture(s->merged);s->merged = NULL;
6346                                 R_PurgeTexture(s->base  );s->base   = NULL;
6347                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6348                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6349                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6350                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6351                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6352                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6353                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6354                                 s->loadsequence = 0;
6355                         }
6356                 }
6357         }
6358 }
6359
6360 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6361         skinframe_t *item;
6362         char basename[MAX_QPATH];
6363
6364         Image_StripImageExtension(name, basename, sizeof(basename));
6365
6366         if( last == NULL ) {
6367                 int hashindex;
6368                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6369                 item = r_skinframe.hash[hashindex];
6370         } else {
6371                 item = last->next;
6372         }
6373
6374         // linearly search through the hash bucket
6375         for( ; item ; item = item->next ) {
6376                 if( !strcmp( item->basename, basename ) ) {
6377                         return item;
6378                 }
6379         }
6380         return NULL;
6381 }
6382
6383 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6384 {
6385         skinframe_t *item;
6386         int hashindex;
6387         char basename[MAX_QPATH];
6388
6389         Image_StripImageExtension(name, basename, sizeof(basename));
6390
6391         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6392         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6393                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6394                         break;
6395
6396         if (!item) {
6397                 rtexture_t *dyntexture;
6398                 // check whether its a dynamic texture
6399                 dyntexture = CL_GetDynTexture( basename );
6400                 if (!add && !dyntexture)
6401                         return NULL;
6402                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6403                 memset(item, 0, sizeof(*item));
6404                 strlcpy(item->basename, basename, sizeof(item->basename));
6405                 item->base = dyntexture; // either NULL or dyntexture handle
6406                 item->textureflags = textureflags;
6407                 item->comparewidth = comparewidth;
6408                 item->compareheight = compareheight;
6409                 item->comparecrc = comparecrc;
6410                 item->next = r_skinframe.hash[hashindex];
6411                 r_skinframe.hash[hashindex] = item;
6412         }
6413         else if( item->base == NULL )
6414         {
6415                 rtexture_t *dyntexture;
6416                 // check whether its a dynamic texture
6417                 // 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]
6418                 dyntexture = CL_GetDynTexture( basename );
6419                 item->base = dyntexture; // either NULL or dyntexture handle
6420         }
6421
6422         R_SkinFrame_MarkUsed(item);
6423         return item;
6424 }
6425
6426 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6427         { \
6428                 unsigned long long avgcolor[5], wsum; \
6429                 int pix, comp, w; \
6430                 avgcolor[0] = 0; \
6431                 avgcolor[1] = 0; \
6432                 avgcolor[2] = 0; \
6433                 avgcolor[3] = 0; \
6434                 avgcolor[4] = 0; \
6435                 wsum = 0; \
6436                 for(pix = 0; pix < cnt; ++pix) \
6437                 { \
6438                         w = 0; \
6439                         for(comp = 0; comp < 3; ++comp) \
6440                                 w += getpixel; \
6441                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6442                         { \
6443                                 ++wsum; \
6444                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6445                                 w = getpixel; \
6446                                 for(comp = 0; comp < 3; ++comp) \
6447                                         avgcolor[comp] += getpixel * w; \
6448                                 avgcolor[3] += w; \
6449                         } \
6450                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6451                         avgcolor[4] += getpixel; \
6452                 } \
6453                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6454                         avgcolor[3] = 1; \
6455                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6456                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6457                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6458                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6459         }
6460
6461 extern cvar_t gl_picmip;
6462 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6463 {
6464         int j;
6465         unsigned char *pixels;
6466         unsigned char *bumppixels;
6467         unsigned char *basepixels = NULL;
6468         int basepixels_width = 0;
6469         int basepixels_height = 0;
6470         skinframe_t *skinframe;
6471         rtexture_t *ddsbase = NULL;
6472         qboolean ddshasalpha = false;
6473         float ddsavgcolor[4];
6474         char basename[MAX_QPATH];
6475         int miplevel = R_PicmipForFlags(textureflags);
6476         int savemiplevel = miplevel;
6477         int mymiplevel;
6478
6479         if (cls.state == ca_dedicated)
6480                 return NULL;
6481
6482         // return an existing skinframe if already loaded
6483         // if loading of the first image fails, don't make a new skinframe as it
6484         // would cause all future lookups of this to be missing
6485         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6486         if (skinframe && skinframe->base)
6487                 return skinframe;
6488
6489         Image_StripImageExtension(name, basename, sizeof(basename));
6490
6491         // check for DDS texture file first
6492         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6493         {
6494                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6495                 if (basepixels == NULL)
6496                         return NULL;
6497         }
6498
6499         // FIXME handle miplevel
6500
6501         if (developer_loading.integer)
6502                 Con_Printf("loading skin \"%s\"\n", name);
6503
6504         // we've got some pixels to store, so really allocate this new texture now
6505         if (!skinframe)
6506                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6507         skinframe->stain = NULL;
6508         skinframe->merged = NULL;
6509         skinframe->base = NULL;
6510         skinframe->pants = NULL;
6511         skinframe->shirt = NULL;
6512         skinframe->nmap = NULL;
6513         skinframe->gloss = NULL;
6514         skinframe->glow = NULL;
6515         skinframe->fog = NULL;
6516         skinframe->reflect = NULL;
6517         skinframe->hasalpha = false;
6518
6519         if (ddsbase)
6520         {
6521                 skinframe->base = ddsbase;
6522                 skinframe->hasalpha = ddshasalpha;
6523                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6524                 if (r_loadfog && skinframe->hasalpha)
6525                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6526                 //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]);
6527         }
6528         else
6529         {
6530                 basepixels_width = image_width;
6531                 basepixels_height = image_height;
6532                 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);
6533                 if (textureflags & TEXF_ALPHA)
6534                 {
6535                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6536                         {
6537                                 if (basepixels[j] < 255)
6538                                 {
6539                                         skinframe->hasalpha = true;
6540                                         break;
6541                                 }
6542                         }
6543                         if (r_loadfog && skinframe->hasalpha)
6544                         {
6545                                 // has transparent pixels
6546                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6547                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6548                                 {
6549                                         pixels[j+0] = 255;
6550                                         pixels[j+1] = 255;
6551                                         pixels[j+2] = 255;
6552                                         pixels[j+3] = basepixels[j+3];
6553                                 }
6554                                 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);
6555                                 Mem_Free(pixels);
6556                         }
6557                 }
6558                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6559                 //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]);
6560                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6561                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6562                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6563                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6564         }
6565
6566         if (r_loaddds)
6567         {
6568                 mymiplevel = savemiplevel;
6569                 if (r_loadnormalmap)
6570                         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);
6571                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6572                 if (r_loadgloss)
6573                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6574                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6575                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6576                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6577         }
6578
6579         // _norm is the name used by tenebrae and has been adopted as standard
6580         if (r_loadnormalmap && skinframe->nmap == NULL)
6581         {
6582                 mymiplevel = savemiplevel;
6583                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6584                 {
6585                         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);
6586                         Mem_Free(pixels);
6587                         pixels = NULL;
6588                 }
6589                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6590                 {
6591                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6592                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
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                         Mem_Free(bumppixels);
6596                 }
6597                 else if (r_shadow_bumpscale_basetexture.value > 0)
6598                 {
6599                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6600                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6601                         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);
6602                         Mem_Free(pixels);
6603                 }
6604                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6605                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6606         }
6607
6608         // _luma is supported only for tenebrae compatibility
6609         // _glow is the preferred name
6610         mymiplevel = savemiplevel;
6611         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))))
6612         {
6613                 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);
6614                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6615                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6616                 Mem_Free(pixels);pixels = NULL;
6617         }
6618
6619         mymiplevel = savemiplevel;
6620         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6621         {
6622                 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);
6623                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6624                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6625                 Mem_Free(pixels);
6626                 pixels = NULL;
6627         }
6628
6629         mymiplevel = savemiplevel;
6630         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6631         {
6632                 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);
6633                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6634                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6635                 Mem_Free(pixels);
6636                 pixels = NULL;
6637         }
6638
6639         mymiplevel = savemiplevel;
6640         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6641         {
6642                 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);
6643                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6644                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6645                 Mem_Free(pixels);
6646                 pixels = NULL;
6647         }
6648
6649         mymiplevel = savemiplevel;
6650         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6651         {
6652                 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);
6653                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6654                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6655                 Mem_Free(pixels);
6656                 pixels = NULL;
6657         }
6658
6659         if (basepixels)
6660                 Mem_Free(basepixels);
6661
6662         return skinframe;
6663 }
6664
6665 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6666 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6667 {
6668         int i;
6669         unsigned char *temp1, *temp2;
6670         skinframe_t *skinframe;
6671
6672         if (cls.state == ca_dedicated)
6673                 return NULL;
6674
6675         // if already loaded just return it, otherwise make a new skinframe
6676         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6677         if (skinframe && skinframe->base)
6678                 return skinframe;
6679
6680         skinframe->stain = NULL;
6681         skinframe->merged = NULL;
6682         skinframe->base = NULL;
6683         skinframe->pants = NULL;
6684         skinframe->shirt = NULL;
6685         skinframe->nmap = NULL;
6686         skinframe->gloss = NULL;
6687         skinframe->glow = NULL;
6688         skinframe->fog = NULL;
6689         skinframe->reflect = NULL;
6690         skinframe->hasalpha = false;
6691
6692         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6693         if (!skindata)
6694                 return NULL;
6695
6696         if (developer_loading.integer)
6697                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6698
6699         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6700         {
6701                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6702                 temp2 = temp1 + width * height * 4;
6703                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6704                 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);
6705                 Mem_Free(temp1);
6706         }
6707         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6708         if (textureflags & TEXF_ALPHA)
6709         {
6710                 for (i = 3;i < width * height * 4;i += 4)
6711                 {
6712                         if (skindata[i] < 255)
6713                         {
6714                                 skinframe->hasalpha = true;
6715                                 break;
6716                         }
6717                 }
6718                 if (r_loadfog && skinframe->hasalpha)
6719                 {
6720                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6721                         memcpy(fogpixels, skindata, width * height * 4);
6722                         for (i = 0;i < width * height * 4;i += 4)
6723                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6724                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6725                         Mem_Free(fogpixels);
6726                 }
6727         }
6728
6729         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6730         //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]);
6731
6732         return skinframe;
6733 }
6734
6735 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6736 {
6737         int i;
6738         int featuresmask;
6739         skinframe_t *skinframe;
6740
6741         if (cls.state == ca_dedicated)
6742                 return NULL;
6743
6744         // if already loaded just return it, otherwise make a new skinframe
6745         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6746         if (skinframe && skinframe->base)
6747                 return skinframe;
6748
6749         skinframe->stain = NULL;
6750         skinframe->merged = NULL;
6751         skinframe->base = NULL;
6752         skinframe->pants = NULL;
6753         skinframe->shirt = NULL;
6754         skinframe->nmap = NULL;
6755         skinframe->gloss = NULL;
6756         skinframe->glow = NULL;
6757         skinframe->fog = NULL;
6758         skinframe->reflect = NULL;
6759         skinframe->hasalpha = false;
6760
6761         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6762         if (!skindata)
6763                 return NULL;
6764
6765         if (developer_loading.integer)
6766                 Con_Printf("loading quake skin \"%s\"\n", name);
6767
6768         // 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)
6769         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6770         memcpy(skinframe->qpixels, skindata, width*height);
6771         skinframe->qwidth = width;
6772         skinframe->qheight = height;
6773
6774         featuresmask = 0;
6775         for (i = 0;i < width * height;i++)
6776                 featuresmask |= palette_featureflags[skindata[i]];
6777
6778         skinframe->hasalpha = false;
6779         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6780         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6781         skinframe->qgeneratemerged = true;
6782         skinframe->qgeneratebase = skinframe->qhascolormapping;
6783         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6784
6785         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6786         //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]);
6787
6788         return skinframe;
6789 }
6790
6791 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6792 {
6793         int width;
6794         int height;
6795         unsigned char *skindata;
6796
6797         if (!skinframe->qpixels)
6798                 return;
6799
6800         if (!skinframe->qhascolormapping)
6801                 colormapped = false;
6802
6803         if (colormapped)
6804         {
6805                 if (!skinframe->qgeneratebase)
6806                         return;
6807         }
6808         else
6809         {
6810                 if (!skinframe->qgeneratemerged)
6811                         return;
6812         }
6813
6814         width = skinframe->qwidth;
6815         height = skinframe->qheight;
6816         skindata = skinframe->qpixels;
6817
6818         if (skinframe->qgeneratenmap)
6819         {
6820                 unsigned char *temp1, *temp2;
6821                 skinframe->qgeneratenmap = false;
6822                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6823                 temp2 = temp1 + width * height * 4;
6824                 // use either a custom palette or the quake palette
6825                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6826                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6827                 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);
6828                 Mem_Free(temp1);
6829         }
6830
6831         if (skinframe->qgenerateglow)
6832         {
6833                 skinframe->qgenerateglow = false;
6834                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6835         }
6836
6837         if (colormapped)
6838         {
6839                 skinframe->qgeneratebase = false;
6840                 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);
6841                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6842                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6843         }
6844         else
6845         {
6846                 skinframe->qgeneratemerged = false;
6847                 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);
6848         }
6849
6850         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6851         {
6852                 Mem_Free(skinframe->qpixels);
6853                 skinframe->qpixels = NULL;
6854         }
6855 }
6856
6857 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)
6858 {
6859         int i;
6860         skinframe_t *skinframe;
6861
6862         if (cls.state == ca_dedicated)
6863                 return NULL;
6864
6865         // if already loaded just return it, otherwise make a new skinframe
6866         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6867         if (skinframe && skinframe->base)
6868                 return skinframe;
6869
6870         skinframe->stain = NULL;
6871         skinframe->merged = NULL;
6872         skinframe->base = NULL;
6873         skinframe->pants = NULL;
6874         skinframe->shirt = NULL;
6875         skinframe->nmap = NULL;
6876         skinframe->gloss = NULL;
6877         skinframe->glow = NULL;
6878         skinframe->fog = NULL;
6879         skinframe->reflect = NULL;
6880         skinframe->hasalpha = false;
6881
6882         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6883         if (!skindata)
6884                 return NULL;
6885
6886         if (developer_loading.integer)
6887                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6888
6889         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6890         if (textureflags & TEXF_ALPHA)
6891         {
6892                 for (i = 0;i < width * height;i++)
6893                 {
6894                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6895                         {
6896                                 skinframe->hasalpha = true;
6897                                 break;
6898                         }
6899                 }
6900                 if (r_loadfog && skinframe->hasalpha)
6901                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6902         }
6903
6904         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6905         //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]);
6906
6907         return skinframe;
6908 }
6909
6910 skinframe_t *R_SkinFrame_LoadMissing(void)
6911 {
6912         skinframe_t *skinframe;
6913
6914         if (cls.state == ca_dedicated)
6915                 return NULL;
6916
6917         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6918         skinframe->stain = NULL;
6919         skinframe->merged = NULL;
6920         skinframe->base = NULL;
6921         skinframe->pants = NULL;
6922         skinframe->shirt = NULL;
6923         skinframe->nmap = NULL;
6924         skinframe->gloss = NULL;
6925         skinframe->glow = NULL;
6926         skinframe->fog = NULL;
6927         skinframe->reflect = NULL;
6928         skinframe->hasalpha = false;
6929
6930         skinframe->avgcolor[0] = rand() / RAND_MAX;
6931         skinframe->avgcolor[1] = rand() / RAND_MAX;
6932         skinframe->avgcolor[2] = rand() / RAND_MAX;
6933         skinframe->avgcolor[3] = 1;
6934
6935         return skinframe;
6936 }
6937
6938 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6939 typedef struct suffixinfo_s
6940 {
6941         const char *suffix;
6942         qboolean flipx, flipy, flipdiagonal;
6943 }
6944 suffixinfo_t;
6945 static suffixinfo_t suffix[3][6] =
6946 {
6947         {
6948                 {"px",   false, false, false},
6949                 {"nx",   false, false, false},
6950                 {"py",   false, false, false},
6951                 {"ny",   false, false, false},
6952                 {"pz",   false, false, false},
6953                 {"nz",   false, false, false}
6954         },
6955         {
6956                 {"posx", false, false, false},
6957                 {"negx", false, false, false},
6958                 {"posy", false, false, false},
6959                 {"negy", false, false, false},
6960                 {"posz", false, false, false},
6961                 {"negz", false, false, false}
6962         },
6963         {
6964                 {"rt",    true, false,  true},
6965                 {"lf",   false,  true,  true},
6966                 {"ft",    true,  true, false},
6967                 {"bk",   false, false, false},
6968                 {"up",    true, false,  true},
6969                 {"dn",    true, false,  true}
6970         }
6971 };
6972
6973 static int componentorder[4] = {0, 1, 2, 3};
6974
6975 rtexture_t *R_LoadCubemap(const char *basename)
6976 {
6977         int i, j, cubemapsize;
6978         unsigned char *cubemappixels, *image_buffer;
6979         rtexture_t *cubemaptexture;
6980         char name[256];
6981         // must start 0 so the first loadimagepixels has no requested width/height
6982         cubemapsize = 0;
6983         cubemappixels = NULL;
6984         cubemaptexture = NULL;
6985         // keep trying different suffix groups (posx, px, rt) until one loads
6986         for (j = 0;j < 3 && !cubemappixels;j++)
6987         {
6988                 // load the 6 images in the suffix group
6989                 for (i = 0;i < 6;i++)
6990                 {
6991                         // generate an image name based on the base and and suffix
6992                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6993                         // load it
6994                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6995                         {
6996                                 // an image loaded, make sure width and height are equal
6997                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6998                                 {
6999                                         // if this is the first image to load successfully, allocate the cubemap memory
7000                                         if (!cubemappixels && image_width >= 1)
7001                                         {
7002                                                 cubemapsize = image_width;
7003                                                 // note this clears to black, so unavailable sides are black
7004                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7005                                         }
7006                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7007                                         if (cubemappixels)
7008                                                 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);
7009                                 }
7010                                 else
7011                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7012                                 // free the image
7013                                 Mem_Free(image_buffer);
7014                         }
7015                 }
7016         }
7017         // if a cubemap loaded, upload it
7018         if (cubemappixels)
7019         {
7020                 if (developer_loading.integer)
7021                         Con_Printf("loading cubemap \"%s\"\n", basename);
7022
7023                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7024                 Mem_Free(cubemappixels);
7025         }
7026         else
7027         {
7028                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7029                 if (developer_loading.integer)
7030                 {
7031                         Con_Printf("(tried tried images ");
7032                         for (j = 0;j < 3;j++)
7033                                 for (i = 0;i < 6;i++)
7034                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7035                         Con_Print(" and was unable to find any of them).\n");
7036                 }
7037         }
7038         return cubemaptexture;
7039 }
7040
7041 rtexture_t *R_GetCubemap(const char *basename)
7042 {
7043         int i;
7044         for (i = 0;i < r_texture_numcubemaps;i++)
7045                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7046                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7047         if (i >= MAX_CUBEMAPS)
7048                 return r_texture_whitecube;
7049         r_texture_numcubemaps++;
7050         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7051         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7052         return r_texture_cubemaps[i].texture;
7053 }
7054
7055 void R_FreeCubemaps(void)
7056 {
7057         int i;
7058         for (i = 0;i < r_texture_numcubemaps;i++)
7059         {
7060                 if (developer_loading.integer)
7061                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7062                 if (r_texture_cubemaps[i].texture)
7063                         R_FreeTexture(r_texture_cubemaps[i].texture);
7064         }
7065         r_texture_numcubemaps = 0;
7066 }
7067
7068 void R_Main_FreeViewCache(void)
7069 {
7070         if (r_refdef.viewcache.entityvisible)
7071                 Mem_Free(r_refdef.viewcache.entityvisible);
7072         if (r_refdef.viewcache.world_pvsbits)
7073                 Mem_Free(r_refdef.viewcache.world_pvsbits);
7074         if (r_refdef.viewcache.world_leafvisible)
7075                 Mem_Free(r_refdef.viewcache.world_leafvisible);
7076         if (r_refdef.viewcache.world_surfacevisible)
7077                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7078         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7079 }
7080
7081 void R_Main_ResizeViewCache(void)
7082 {
7083         int numentities = r_refdef.scene.numentities;
7084         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7085         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7086         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7087         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7088         if (r_refdef.viewcache.maxentities < numentities)
7089         {
7090                 r_refdef.viewcache.maxentities = numentities;
7091                 if (r_refdef.viewcache.entityvisible)
7092                         Mem_Free(r_refdef.viewcache.entityvisible);
7093                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7094         }
7095         if (r_refdef.viewcache.world_numclusters != numclusters)
7096         {
7097                 r_refdef.viewcache.world_numclusters = numclusters;
7098                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7099                 if (r_refdef.viewcache.world_pvsbits)
7100                         Mem_Free(r_refdef.viewcache.world_pvsbits);
7101                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7102         }
7103         if (r_refdef.viewcache.world_numleafs != numleafs)
7104         {
7105                 r_refdef.viewcache.world_numleafs = numleafs;
7106                 if (r_refdef.viewcache.world_leafvisible)
7107                         Mem_Free(r_refdef.viewcache.world_leafvisible);
7108                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7109         }
7110         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7111         {
7112                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7113                 if (r_refdef.viewcache.world_surfacevisible)
7114                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
7115                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7116         }
7117 }
7118
7119 extern rtexture_t *loadingscreentexture;
7120 void gl_main_start(void)
7121 {
7122         loadingscreentexture = NULL;
7123         r_texture_blanknormalmap = NULL;
7124         r_texture_white = NULL;
7125         r_texture_grey128 = NULL;
7126         r_texture_black = NULL;
7127         r_texture_whitecube = NULL;
7128         r_texture_normalizationcube = NULL;
7129         r_texture_fogattenuation = NULL;
7130         r_texture_fogheighttexture = NULL;
7131         r_texture_gammaramps = NULL;
7132         r_texture_numcubemaps = 0;
7133
7134         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
7135         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7136
7137         switch(vid.renderpath)
7138         {
7139         case RENDERPATH_GL20:
7140         case RENDERPATH_CGGL:
7141         case RENDERPATH_D3D9:
7142         case RENDERPATH_D3D10:
7143         case RENDERPATH_D3D11:
7144                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7145                 Cvar_SetValueQuick(&gl_combine, 1);
7146                 Cvar_SetValueQuick(&r_glsl, 1);
7147                 r_loadnormalmap = true;
7148                 r_loadgloss = true;
7149                 r_loadfog = false;
7150                 break;
7151         case RENDERPATH_GL13:
7152                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7153                 Cvar_SetValueQuick(&gl_combine, 1);
7154                 Cvar_SetValueQuick(&r_glsl, 0);
7155                 r_loadnormalmap = false;
7156                 r_loadgloss = false;
7157                 r_loadfog = true;
7158                 break;
7159         case RENDERPATH_GL11:
7160                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7161                 Cvar_SetValueQuick(&gl_combine, 0);
7162                 Cvar_SetValueQuick(&r_glsl, 0);
7163                 r_loadnormalmap = false;
7164                 r_loadgloss = false;
7165                 r_loadfog = true;
7166                 break;
7167         }
7168
7169         R_AnimCache_Free();
7170         R_FrameData_Reset();
7171
7172         r_numqueries = 0;
7173         r_maxqueries = 0;
7174         memset(r_queries, 0, sizeof(r_queries));
7175
7176         r_qwskincache = NULL;
7177         r_qwskincache_size = 0;
7178
7179         // set up r_skinframe loading system for textures
7180         memset(&r_skinframe, 0, sizeof(r_skinframe));
7181         r_skinframe.loadsequence = 1;
7182         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7183
7184         r_main_texturepool = R_AllocTexturePool();
7185         R_BuildBlankTextures();
7186         R_BuildNoTexture();
7187         if (vid.support.arb_texture_cube_map)
7188         {
7189                 R_BuildWhiteCube();
7190                 R_BuildNormalizationCube();
7191         }
7192         r_texture_fogattenuation = NULL;
7193         r_texture_fogheighttexture = NULL;
7194         r_texture_gammaramps = NULL;
7195         //r_texture_fogintensity = NULL;
7196         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7197         memset(&r_waterstate, 0, sizeof(r_waterstate));
7198         r_glsl_permutation = NULL;
7199         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7200         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7201         glslshaderstring = NULL;
7202 #ifdef SUPPORTCG
7203         r_cg_permutation = NULL;
7204         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7205         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7206         cgshaderstring = NULL;
7207 #endif
7208 #ifdef SUPPORTD3D
7209         r_hlsl_permutation = NULL;
7210         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7211         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7212         hlslshaderstring = NULL;
7213 #endif
7214         memset(&r_svbsp, 0, sizeof (r_svbsp));
7215
7216         r_refdef.fogmasktable_density = 0;
7217 }
7218
7219 void gl_main_shutdown(void)
7220 {
7221         R_AnimCache_Free();
7222         R_FrameData_Reset();
7223
7224         R_Main_FreeViewCache();
7225
7226         switch(vid.renderpath)
7227         {
7228         case RENDERPATH_GL11:
7229         case RENDERPATH_GL13:
7230         case RENDERPATH_GL20:
7231         case RENDERPATH_CGGL:
7232                 if (r_maxqueries)
7233                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7234                 break;
7235         case RENDERPATH_D3D9:
7236                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7237                 break;
7238         case RENDERPATH_D3D10:
7239                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7240                 break;
7241         case RENDERPATH_D3D11:
7242                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7243                 break;
7244         }
7245
7246         r_numqueries = 0;
7247         r_maxqueries = 0;
7248         memset(r_queries, 0, sizeof(r_queries));
7249
7250         r_qwskincache = NULL;
7251         r_qwskincache_size = 0;
7252
7253         // clear out the r_skinframe state
7254         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7255         memset(&r_skinframe, 0, sizeof(r_skinframe));
7256
7257         if (r_svbsp.nodes)
7258                 Mem_Free(r_svbsp.nodes);
7259         memset(&r_svbsp, 0, sizeof (r_svbsp));
7260         R_FreeTexturePool(&r_main_texturepool);
7261         loadingscreentexture = NULL;
7262         r_texture_blanknormalmap = NULL;
7263         r_texture_white = NULL;
7264         r_texture_grey128 = NULL;
7265         r_texture_black = NULL;
7266         r_texture_whitecube = NULL;
7267         r_texture_normalizationcube = NULL;
7268         r_texture_fogattenuation = NULL;
7269         r_texture_fogheighttexture = NULL;
7270         r_texture_gammaramps = NULL;
7271         r_texture_numcubemaps = 0;
7272         //r_texture_fogintensity = NULL;
7273         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7274         memset(&r_waterstate, 0, sizeof(r_waterstate));
7275         R_GLSL_Restart_f();
7276 }
7277
7278 extern void CL_ParseEntityLump(char *entitystring);
7279 void gl_main_newmap(void)
7280 {
7281         // FIXME: move this code to client
7282         char *entities, entname[MAX_QPATH];
7283         if (r_qwskincache)
7284                 Mem_Free(r_qwskincache);
7285         r_qwskincache = NULL;
7286         r_qwskincache_size = 0;
7287         if (cl.worldmodel)
7288         {
7289                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7290                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7291                 {
7292                         CL_ParseEntityLump(entities);
7293                         Mem_Free(entities);
7294                         return;
7295                 }
7296                 if (cl.worldmodel->brush.entities)
7297                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7298         }
7299         R_Main_FreeViewCache();
7300
7301         R_FrameData_Reset();
7302 }
7303
7304 void GL_Main_Init(void)
7305 {
7306         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7307
7308         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7309         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7310         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7311         if (gamemode == GAME_NEHAHRA)
7312         {
7313                 Cvar_RegisterVariable (&gl_fogenable);
7314                 Cvar_RegisterVariable (&gl_fogdensity);
7315                 Cvar_RegisterVariable (&gl_fogred);
7316                 Cvar_RegisterVariable (&gl_foggreen);
7317                 Cvar_RegisterVariable (&gl_fogblue);
7318                 Cvar_RegisterVariable (&gl_fogstart);
7319                 Cvar_RegisterVariable (&gl_fogend);
7320                 Cvar_RegisterVariable (&gl_skyclip);
7321         }
7322         Cvar_RegisterVariable(&r_motionblur);
7323         Cvar_RegisterVariable(&r_motionblur_maxblur);
7324         Cvar_RegisterVariable(&r_motionblur_bmin);
7325         Cvar_RegisterVariable(&r_motionblur_vmin);
7326         Cvar_RegisterVariable(&r_motionblur_vmax);
7327         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7328         Cvar_RegisterVariable(&r_motionblur_randomize);
7329         Cvar_RegisterVariable(&r_damageblur);
7330         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7331         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7332         Cvar_RegisterVariable(&r_equalize_entities_by);
7333         Cvar_RegisterVariable(&r_equalize_entities_to);
7334         Cvar_RegisterVariable(&r_depthfirst);
7335         Cvar_RegisterVariable(&r_useinfinitefarclip);
7336         Cvar_RegisterVariable(&r_farclip_base);
7337         Cvar_RegisterVariable(&r_farclip_world);
7338         Cvar_RegisterVariable(&r_nearclip);
7339         Cvar_RegisterVariable(&r_showbboxes);
7340         Cvar_RegisterVariable(&r_showsurfaces);
7341         Cvar_RegisterVariable(&r_showtris);
7342         Cvar_RegisterVariable(&r_shownormals);
7343         Cvar_RegisterVariable(&r_showlighting);
7344         Cvar_RegisterVariable(&r_showshadowvolumes);
7345         Cvar_RegisterVariable(&r_showcollisionbrushes);
7346         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7347         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7348         Cvar_RegisterVariable(&r_showdisabledepthtest);
7349         Cvar_RegisterVariable(&r_drawportals);
7350         Cvar_RegisterVariable(&r_drawentities);
7351         Cvar_RegisterVariable(&r_draw2d);
7352         Cvar_RegisterVariable(&r_drawworld);
7353         Cvar_RegisterVariable(&r_cullentities_trace);
7354         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7355         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7356         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7357         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7358         Cvar_RegisterVariable(&r_drawviewmodel);
7359         Cvar_RegisterVariable(&r_drawexteriormodel);
7360         Cvar_RegisterVariable(&r_speeds);
7361         Cvar_RegisterVariable(&r_fullbrights);
7362         Cvar_RegisterVariable(&r_wateralpha);
7363         Cvar_RegisterVariable(&r_dynamic);
7364         Cvar_RegisterVariable(&r_fakelight);
7365         Cvar_RegisterVariable(&r_fakelight_intensity);
7366         Cvar_RegisterVariable(&r_fullbright);
7367         Cvar_RegisterVariable(&r_shadows);
7368         Cvar_RegisterVariable(&r_shadows_darken);
7369         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7370         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7371         Cvar_RegisterVariable(&r_shadows_throwdistance);
7372         Cvar_RegisterVariable(&r_shadows_throwdirection);
7373         Cvar_RegisterVariable(&r_shadows_focus);
7374         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7375         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7376         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7377         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7378         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7379         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7380         Cvar_RegisterVariable(&r_fog_exp2);
7381         Cvar_RegisterVariable(&r_drawfog);
7382         Cvar_RegisterVariable(&r_transparentdepthmasking);
7383         Cvar_RegisterVariable(&r_texture_dds_load);
7384         Cvar_RegisterVariable(&r_texture_dds_save);
7385         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7386         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7387         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7388         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7389         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7390         Cvar_RegisterVariable(&r_textureunits);
7391         Cvar_RegisterVariable(&gl_combine);
7392         Cvar_RegisterVariable(&r_glsl);
7393         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7394         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7395         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7396         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7397         Cvar_RegisterVariable(&r_glsl_postprocess);
7398         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7399         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7400         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7401         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7402         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
7403         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
7404         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
7405         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
7406
7407         Cvar_RegisterVariable(&r_water);
7408         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7409         Cvar_RegisterVariable(&r_water_clippingplanebias);
7410         Cvar_RegisterVariable(&r_water_refractdistort);
7411         Cvar_RegisterVariable(&r_water_reflectdistort);
7412         Cvar_RegisterVariable(&r_water_scissormode);
7413         Cvar_RegisterVariable(&r_lerpsprites);
7414         Cvar_RegisterVariable(&r_lerpmodels);
7415         Cvar_RegisterVariable(&r_lerplightstyles);
7416         Cvar_RegisterVariable(&r_waterscroll);
7417         Cvar_RegisterVariable(&r_bloom);
7418         Cvar_RegisterVariable(&r_bloom_colorscale);
7419         Cvar_RegisterVariable(&r_bloom_brighten);
7420         Cvar_RegisterVariable(&r_bloom_blur);
7421         Cvar_RegisterVariable(&r_bloom_resolution);
7422         Cvar_RegisterVariable(&r_bloom_colorexponent);
7423         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7424         Cvar_RegisterVariable(&r_hdr);
7425         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7426         Cvar_RegisterVariable(&r_hdr_glowintensity);
7427         Cvar_RegisterVariable(&r_hdr_range);
7428         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7429         Cvar_RegisterVariable(&developer_texturelogging);
7430         Cvar_RegisterVariable(&gl_lightmaps);
7431         Cvar_RegisterVariable(&r_test);
7432         Cvar_RegisterVariable(&r_glsl_saturation);
7433         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7434         Cvar_RegisterVariable(&r_framedatasize);
7435         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7436                 Cvar_SetValue("r_fullbrights", 0);
7437         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7438
7439         Cvar_RegisterVariable(&r_track_sprites);
7440         Cvar_RegisterVariable(&r_track_sprites_flags);
7441         Cvar_RegisterVariable(&r_track_sprites_scalew);
7442         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7443         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7444         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7445 }
7446
7447 extern void R_Textures_Init(void);
7448 extern void GL_Draw_Init(void);
7449 extern void GL_Main_Init(void);
7450 extern void R_Shadow_Init(void);
7451 extern void R_Sky_Init(void);
7452 extern void GL_Surf_Init(void);
7453 extern void R_Particles_Init(void);
7454 extern void R_Explosion_Init(void);
7455 extern void gl_backend_init(void);
7456 extern void Sbar_Init(void);
7457 extern void R_LightningBeams_Init(void);
7458 extern void Mod_RenderInit(void);
7459 extern void Font_Init(void);
7460
7461 void Render_Init(void)
7462 {
7463         gl_backend_init();
7464         R_Textures_Init();
7465         GL_Main_Init();
7466         Font_Init();
7467         GL_Draw_Init();
7468         R_Shadow_Init();
7469         R_Sky_Init();
7470         GL_Surf_Init();
7471         Sbar_Init();
7472         R_Particles_Init();
7473         R_Explosion_Init();
7474         R_LightningBeams_Init();
7475         Mod_RenderInit();
7476 }
7477
7478 /*
7479 ===============
7480 GL_Init
7481 ===============
7482 */
7483 extern char *ENGINE_EXTENSIONS;
7484 void GL_Init (void)
7485 {
7486         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7487         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7488         gl_version = (const char *)qglGetString(GL_VERSION);
7489         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7490
7491         if (!gl_extensions)
7492                 gl_extensions = "";
7493         if (!gl_platformextensions)
7494                 gl_platformextensions = "";
7495
7496         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7497         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7498         Con_Printf("GL_VERSION: %s\n", gl_version);
7499         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7500         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7501
7502         VID_CheckExtensions();
7503
7504         // LordHavoc: report supported extensions
7505         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7506
7507         // clear to black (loading plaque will be seen over this)
7508         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7509 }
7510
7511 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7512 {
7513         int i;
7514         mplane_t *p;
7515         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7516         {
7517                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7518                 if (i == 4)
7519                         continue;
7520                 p = r_refdef.view.frustum + i;
7521                 switch(p->signbits)
7522                 {
7523                 default:
7524                 case 0:
7525                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7526                                 return true;
7527                         break;
7528                 case 1:
7529                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7530                                 return true;
7531                         break;
7532                 case 2:
7533                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7534                                 return true;
7535                         break;
7536                 case 3:
7537                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7538                                 return true;
7539                         break;
7540                 case 4:
7541                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7542                                 return true;
7543                         break;
7544                 case 5:
7545                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7546                                 return true;
7547                         break;
7548                 case 6:
7549                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7550                                 return true;
7551                         break;
7552                 case 7:
7553                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7554                                 return true;
7555                         break;
7556                 }
7557         }
7558         return false;
7559 }
7560
7561 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7562 {
7563         int i;
7564         const mplane_t *p;
7565         for (i = 0;i < numplanes;i++)
7566         {
7567                 p = planes + i;
7568                 switch(p->signbits)
7569                 {
7570                 default:
7571                 case 0:
7572                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7573                                 return true;
7574                         break;
7575                 case 1:
7576                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7577                                 return true;
7578                         break;
7579                 case 2:
7580                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7581                                 return true;
7582                         break;
7583                 case 3:
7584                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7585                                 return true;
7586                         break;
7587                 case 4:
7588                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7589                                 return true;
7590                         break;
7591                 case 5:
7592                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7593                                 return true;
7594                         break;
7595                 case 6:
7596                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7597                                 return true;
7598                         break;
7599                 case 7:
7600                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7601                                 return true;
7602                         break;
7603                 }
7604         }
7605         return false;
7606 }
7607
7608 //==================================================================================
7609
7610 // LordHavoc: this stores temporary data used within the same frame
7611
7612 qboolean r_framedata_failed;
7613 static size_t r_framedata_size;
7614 static size_t r_framedata_current;
7615 static void *r_framedata_base;
7616
7617 void R_FrameData_Reset(void)
7618 {
7619         if (r_framedata_base)
7620                 Mem_Free(r_framedata_base);
7621         r_framedata_base = NULL;
7622         r_framedata_size = 0;
7623         r_framedata_current = 0;
7624         r_framedata_failed = false;
7625 }
7626
7627 void R_FrameData_NewFrame(void)
7628 {
7629         size_t wantedsize;
7630         if (r_framedata_failed)
7631                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7632         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7633         wantedsize = bound(65536, wantedsize, 128*1024*1024);
7634         if (r_framedata_size != wantedsize)
7635         {
7636                 r_framedata_size = wantedsize;
7637                 if (r_framedata_base)
7638                         Mem_Free(r_framedata_base);
7639                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7640         }
7641         r_framedata_current = 0;
7642         r_framedata_failed = false;
7643 }
7644
7645 void *R_FrameData_Alloc(size_t size)
7646 {
7647         void *data;
7648
7649         // align to 16 byte boundary
7650         size = (size + 15) & ~15;
7651         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7652         r_framedata_current += size;
7653
7654         // check overflow
7655         if (r_framedata_current > r_framedata_size)
7656                 r_framedata_failed = true;
7657
7658         // return NULL on everything after a failure
7659         if (r_framedata_failed)
7660                 return NULL;
7661
7662         return data;
7663 }
7664
7665 void *R_FrameData_Store(size_t size, void *data)
7666 {
7667         void *d = R_FrameData_Alloc(size);
7668         if (d)
7669                 memcpy(d, data, size);
7670         return d;
7671 }
7672
7673 //==================================================================================
7674
7675 // LordHavoc: animcache originally written by Echon, rewritten since then
7676
7677 /**
7678  * Animation cache prevents re-generating mesh data for an animated model
7679  * multiple times in one frame for lighting, shadowing, reflections, etc.
7680  */
7681
7682 void R_AnimCache_Free(void)
7683 {
7684 }
7685
7686 void R_AnimCache_ClearCache(void)
7687 {
7688         int i;
7689         entity_render_t *ent;
7690
7691         for (i = 0;i < r_refdef.scene.numentities;i++)
7692         {
7693                 ent = r_refdef.scene.entities[i];
7694                 ent->animcache_vertex3f = NULL;
7695                 ent->animcache_normal3f = NULL;
7696                 ent->animcache_svector3f = NULL;
7697                 ent->animcache_tvector3f = NULL;
7698                 ent->animcache_vertexposition = NULL;
7699                 ent->animcache_vertexmesh = NULL;
7700                 ent->animcache_vertexpositionbuffer = NULL;
7701                 ent->animcache_vertexmeshbuffer = NULL;
7702         }
7703 }
7704
7705 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7706 {
7707         int i;
7708
7709         // identical memory layout, so no need to allocate...
7710         // this also provides the vertexposition structure to everything, e.g.
7711         // depth masked rendering currently uses it even if having separate
7712         // arrays
7713         // NOTE: get rid of this optimization if changing it to e.g. 4f
7714         ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7715
7716         // TODO:
7717         // get rid of following uses of VERTEXPOSITION, change to the array:
7718         // R_DrawTextureSurfaceList_Sky if skyrendermasked
7719         // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7720         // R_DrawTextureSurfaceList_DepthOnly
7721         // R_Q1BSP_DrawShadowMap
7722
7723         switch(vid.renderpath)
7724         {
7725         case RENDERPATH_GL20:
7726         case RENDERPATH_CGGL:
7727                 // need the meshbuffers if !gl_mesh_separatearrays.integer
7728                 if (gl_mesh_separatearrays.integer)
7729                         return;
7730                 break;
7731         case RENDERPATH_D3D9:
7732         case RENDERPATH_D3D10:
7733         case RENDERPATH_D3D11:
7734                 // always need the meshbuffers
7735                 break;
7736         case RENDERPATH_GL13:
7737         case RENDERPATH_GL11:
7738                 // never need the meshbuffers
7739                 return;
7740         }
7741
7742         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7743                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7744         /*
7745         if (!ent->animcache_vertexposition)
7746                 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7747         */
7748         if (ent->animcache_vertexposition)
7749         {
7750                 /*
7751                 for (i = 0;i < numvertices;i++)
7752                         memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7753                 */
7754                 // TODO: upload vertex buffer?
7755         }
7756         if (ent->animcache_vertexmesh)
7757         {
7758                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7759                 for (i = 0;i < numvertices;i++)
7760                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7761                 if (ent->animcache_svector3f)
7762                         for (i = 0;i < numvertices;i++)
7763                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7764                 if (ent->animcache_tvector3f)
7765                         for (i = 0;i < numvertices;i++)
7766                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7767                 if (ent->animcache_normal3f)
7768                         for (i = 0;i < numvertices;i++)
7769                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7770                 // TODO: upload vertex buffer?
7771         }
7772 }
7773
7774 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7775 {
7776         dp_model_t *model = ent->model;
7777         int numvertices;
7778         // see if it's already cached this frame
7779         if (ent->animcache_vertex3f)
7780         {
7781                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7782                 if (wantnormals || wanttangents)
7783                 {
7784                         if (ent->animcache_normal3f)
7785                                 wantnormals = false;
7786                         if (ent->animcache_svector3f)
7787                                 wanttangents = false;
7788                         if (wantnormals || wanttangents)
7789                         {
7790                                 numvertices = model->surfmesh.num_vertices;
7791                                 if (wantnormals)
7792                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7793                                 if (wanttangents)
7794                                 {
7795                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7796                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7797                                 }
7798                                 if (!r_framedata_failed)
7799                                 {
7800                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7801                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7802                                 }
7803                         }
7804                 }
7805         }
7806         else
7807         {
7808                 // see if this ent is worth caching
7809                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7810                         return false;
7811                 // get some memory for this entity and generate mesh data
7812                 numvertices = model->surfmesh.num_vertices;
7813                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7814                 if (wantnormals)
7815                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7816                 if (wanttangents)
7817                 {
7818                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7819                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7820                 }
7821                 if (!r_framedata_failed)
7822                 {
7823                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7824                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7825                 }
7826         }
7827         return !r_framedata_failed;
7828 }
7829
7830 void R_AnimCache_CacheVisibleEntities(void)
7831 {
7832         int i;
7833         qboolean wantnormals = true;
7834         qboolean wanttangents = !r_showsurfaces.integer;
7835
7836         switch(vid.renderpath)
7837         {
7838         case RENDERPATH_GL20:
7839         case RENDERPATH_CGGL:
7840         case RENDERPATH_D3D9:
7841         case RENDERPATH_D3D10:
7842         case RENDERPATH_D3D11:
7843                 break;
7844         case RENDERPATH_GL13:
7845         case RENDERPATH_GL11:
7846                 wanttangents = false;
7847                 break;
7848         }
7849
7850         if (r_shownormals.integer)
7851                 wanttangents = wantnormals = true;
7852
7853         // TODO: thread this
7854         // NOTE: R_PrepareRTLights() also caches entities
7855
7856         for (i = 0;i < r_refdef.scene.numentities;i++)
7857                 if (r_refdef.viewcache.entityvisible[i])
7858                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7859 }
7860
7861 //==================================================================================
7862
7863 static void R_View_UpdateEntityLighting (void)
7864 {
7865         int i;
7866         entity_render_t *ent;
7867         vec3_t tempdiffusenormal, avg;
7868         vec_t f, fa, fd, fdd;
7869         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7870
7871         for (i = 0;i < r_refdef.scene.numentities;i++)
7872         {
7873                 ent = r_refdef.scene.entities[i];
7874
7875                 // skip unseen models
7876                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7877                         continue;
7878
7879                 // skip bsp models
7880                 if (ent->model && ent->model->brush.num_leafs)
7881                 {
7882                         // TODO: use modellight for r_ambient settings on world?
7883                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7884                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7885                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7886                         continue;
7887                 }
7888
7889                 // fetch the lighting from the worldmodel data
7890                 VectorClear(ent->modellight_ambient);
7891                 VectorClear(ent->modellight_diffuse);
7892                 VectorClear(tempdiffusenormal);
7893                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7894                 {
7895                         vec3_t org;
7896                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7897
7898                         // complete lightning for lit sprites
7899                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7900                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7901                         {
7902                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7903                                         org[2] = org[2] + r_overheadsprites_pushback.value;
7904                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, true, true);
7905                         }
7906                         else
7907                                 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7908
7909                         if(ent->flags & RENDER_EQUALIZE)
7910                         {
7911                                 // first fix up ambient lighting...
7912                                 if(r_equalize_entities_minambient.value > 0)
7913                                 {
7914                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7915                                         if(fd > 0)
7916                                         {
7917                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7918                                                 if(fa < r_equalize_entities_minambient.value * fd)
7919                                                 {
7920                                                         // solve:
7921                                                         //   fa'/fd' = minambient
7922                                                         //   fa'+0.25*fd' = fa+0.25*fd
7923                                                         //   ...
7924                                                         //   fa' = fd' * minambient
7925                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7926                                                         //   ...
7927                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7928                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7929                                                         //   ...
7930                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7931                                                         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
7932                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7933                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7934                                                 }
7935                                         }
7936                                 }
7937
7938                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7939                                 {
7940                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7941                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7942                                         if(f > 0)
7943                                         {
7944                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7945                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7946                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7947                                         }
7948                                 }
7949                         }
7950                 }
7951                 else // highly rare
7952                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7953
7954                 // move the light direction into modelspace coordinates for lighting code
7955                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7956                 if(VectorLength2(ent->modellight_lightdir) == 0)
7957                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7958                 VectorNormalize(ent->modellight_lightdir);
7959         }
7960 }
7961
7962 #define MAX_LINEOFSIGHTTRACES 64
7963
7964 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7965 {
7966         int i;
7967         vec3_t boxmins, boxmaxs;
7968         vec3_t start;
7969         vec3_t end;
7970         dp_model_t *model = r_refdef.scene.worldmodel;
7971
7972         if (!model || !model->brush.TraceLineOfSight)
7973                 return true;
7974
7975         // expand the box a little
7976         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7977         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7978         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7979         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7980         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7981         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7982
7983         // return true if eye is inside enlarged box
7984         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7985                 return true;
7986
7987         // try center
7988         VectorCopy(eye, start);
7989         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7990         if (model->brush.TraceLineOfSight(model, start, end))
7991                 return true;
7992
7993         // try various random positions
7994         for (i = 0;i < numsamples;i++)
7995         {
7996                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7997                 if (model->brush.TraceLineOfSight(model, start, end))
7998                         return true;
7999         }
8000
8001         return false;
8002 }
8003
8004
8005 static void R_View_UpdateEntityVisible (void)
8006 {
8007         int i;
8008         int renderimask;
8009         int samples;
8010         entity_render_t *ent;
8011
8012         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8013                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8014                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
8015                 :                                                          RENDER_EXTERIORMODEL;
8016         if (!r_drawviewmodel.integer)
8017                 renderimask |= RENDER_VIEWMODEL;
8018         if (!r_drawexteriormodel.integer)
8019                 renderimask |= RENDER_EXTERIORMODEL;
8020         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8021         {
8022                 // worldmodel can check visibility
8023                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8024                 for (i = 0;i < r_refdef.scene.numentities;i++)
8025                 {
8026                         ent = r_refdef.scene.entities[i];
8027                         if (!(ent->flags & renderimask))
8028                         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)))
8029                         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))
8030                                 r_refdef.viewcache.entityvisible[i] = true;
8031                 }
8032                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8033                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8034                 {
8035                         for (i = 0;i < r_refdef.scene.numentities;i++)
8036                         {
8037                                 ent = r_refdef.scene.entities[i];
8038                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8039                                 {
8040                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8041                                         if (samples < 0)
8042                                                 continue; // temp entities do pvs only
8043                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8044                                                 ent->last_trace_visibility = realtime;
8045                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8046                                                 r_refdef.viewcache.entityvisible[i] = 0;
8047                                 }
8048                         }
8049                 }
8050         }
8051         else
8052         {
8053                 // no worldmodel or it can't check visibility
8054                 for (i = 0;i < r_refdef.scene.numentities;i++)
8055                 {
8056                         ent = r_refdef.scene.entities[i];
8057                         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));
8058                 }
8059         }
8060 }
8061
8062 /// only used if skyrendermasked, and normally returns false
8063 int R_DrawBrushModelsSky (void)
8064 {
8065         int i, sky;
8066         entity_render_t *ent;
8067
8068         sky = false;
8069         for (i = 0;i < r_refdef.scene.numentities;i++)
8070         {
8071                 if (!r_refdef.viewcache.entityvisible[i])
8072                         continue;
8073                 ent = r_refdef.scene.entities[i];
8074                 if (!ent->model || !ent->model->DrawSky)
8075                         continue;
8076                 ent->model->DrawSky(ent);
8077                 sky = true;
8078         }
8079         return sky;
8080 }
8081
8082 static void R_DrawNoModel(entity_render_t *ent);
8083 static void R_DrawModels(void)
8084 {
8085         int i;
8086         entity_render_t *ent;
8087
8088         for (i = 0;i < r_refdef.scene.numentities;i++)
8089         {
8090                 if (!r_refdef.viewcache.entityvisible[i])
8091                         continue;
8092                 ent = r_refdef.scene.entities[i];
8093                 r_refdef.stats.entities++;
8094                 if (ent->model && ent->model->Draw != NULL)
8095                         ent->model->Draw(ent);
8096                 else
8097                         R_DrawNoModel(ent);
8098         }
8099 }
8100
8101 static void R_DrawModelsDepth(void)
8102 {
8103         int i;
8104         entity_render_t *ent;
8105
8106         for (i = 0;i < r_refdef.scene.numentities;i++)
8107         {
8108                 if (!r_refdef.viewcache.entityvisible[i])
8109                         continue;
8110                 ent = r_refdef.scene.entities[i];
8111                 if (ent->model && ent->model->DrawDepth != NULL)
8112                         ent->model->DrawDepth(ent);
8113         }
8114 }
8115
8116 static void R_DrawModelsDebug(void)
8117 {
8118         int i;
8119         entity_render_t *ent;
8120
8121         for (i = 0;i < r_refdef.scene.numentities;i++)
8122         {
8123                 if (!r_refdef.viewcache.entityvisible[i])
8124                         continue;
8125                 ent = r_refdef.scene.entities[i];
8126                 if (ent->model && ent->model->DrawDebug != NULL)
8127                         ent->model->DrawDebug(ent);
8128         }
8129 }
8130
8131 static void R_DrawModelsAddWaterPlanes(void)
8132 {
8133         int i;
8134         entity_render_t *ent;
8135
8136         for (i = 0;i < r_refdef.scene.numentities;i++)
8137         {
8138                 if (!r_refdef.viewcache.entityvisible[i])
8139                         continue;
8140                 ent = r_refdef.scene.entities[i];
8141                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8142                         ent->model->DrawAddWaterPlanes(ent);
8143         }
8144 }
8145
8146 static void R_View_SetFrustum(const int *scissor)
8147 {
8148         int i;
8149         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8150         vec3_t forward, left, up, origin, v;
8151
8152         if(scissor)
8153         {
8154                 // flipped x coordinates (because x points left here)
8155                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8156                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8157
8158                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8159                 switch(vid.renderpath)
8160                 {
8161                         case RENDERPATH_D3D9:
8162                         case RENDERPATH_D3D10:
8163                         case RENDERPATH_D3D11:
8164                                 // non-flipped y coordinates
8165                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8166                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8167                                 break;
8168                         case RENDERPATH_GL11:
8169                         case RENDERPATH_GL13:
8170                         case RENDERPATH_GL20:
8171                         case RENDERPATH_CGGL:
8172                                 // non-flipped y coordinates
8173                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8174                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8175                                 break;
8176                 }
8177         }
8178
8179         // we can't trust r_refdef.view.forward and friends in reflected scenes
8180         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8181
8182 #if 0
8183         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8184         r_refdef.view.frustum[0].normal[1] = 0 - 0;
8185         r_refdef.view.frustum[0].normal[2] = -1 - 0;
8186         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8187         r_refdef.view.frustum[1].normal[1] = 0 + 0;
8188         r_refdef.view.frustum[1].normal[2] = -1 + 0;
8189         r_refdef.view.frustum[2].normal[0] = 0 - 0;
8190         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8191         r_refdef.view.frustum[2].normal[2] = -1 - 0;
8192         r_refdef.view.frustum[3].normal[0] = 0 + 0;
8193         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8194         r_refdef.view.frustum[3].normal[2] = -1 + 0;
8195 #endif
8196
8197 #if 0
8198         zNear = r_refdef.nearclip;
8199         nudge = 1.0 - 1.0 / (1<<23);
8200         r_refdef.view.frustum[4].normal[0] = 0 - 0;
8201         r_refdef.view.frustum[4].normal[1] = 0 - 0;
8202         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8203         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8204         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8205         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8206         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8207         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8208 #endif
8209
8210
8211
8212 #if 0
8213         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8214         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8215         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8216         r_refdef.view.frustum[0].dist = m[15] - m[12];
8217
8218         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8219         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8220         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8221         r_refdef.view.frustum[1].dist = m[15] + m[12];
8222
8223         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8224         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8225         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8226         r_refdef.view.frustum[2].dist = m[15] - m[13];
8227
8228         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8229         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8230         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8231         r_refdef.view.frustum[3].dist = m[15] + m[13];
8232
8233         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8234         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8235         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8236         r_refdef.view.frustum[4].dist = m[15] - m[14];
8237
8238         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8239         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8240         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8241         r_refdef.view.frustum[5].dist = m[15] + m[14];
8242 #endif
8243
8244         if (r_refdef.view.useperspective)
8245         {
8246                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8247                 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]);
8248                 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]);
8249                 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]);
8250                 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]);
8251
8252                 // then the normals from the corners relative to origin
8253                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8254                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8255                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8256                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8257
8258                 // in a NORMAL view, forward cross left == up
8259                 // in a REFLECTED view, forward cross left == down
8260                 // so our cross products above need to be adjusted for a left handed coordinate system
8261                 CrossProduct(forward, left, v);
8262                 if(DotProduct(v, up) < 0)
8263                 {
8264                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8265                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8266                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8267                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8268                 }
8269
8270                 // Leaving those out was a mistake, those were in the old code, and they
8271                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8272                 // I couldn't reproduce it after adding those normalizations. --blub
8273                 VectorNormalize(r_refdef.view.frustum[0].normal);
8274                 VectorNormalize(r_refdef.view.frustum[1].normal);
8275                 VectorNormalize(r_refdef.view.frustum[2].normal);
8276                 VectorNormalize(r_refdef.view.frustum[3].normal);
8277
8278                 // make the corners absolute
8279                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8280                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8281                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8282                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8283
8284                 // one more normal
8285                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8286
8287                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8288                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8289                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8290                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8291                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8292         }
8293         else
8294         {
8295                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8296                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8297                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8298                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8299                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8300                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8301                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8302                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8303                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8304                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8305         }
8306         r_refdef.view.numfrustumplanes = 5;
8307
8308         if (r_refdef.view.useclipplane)
8309         {
8310                 r_refdef.view.numfrustumplanes = 6;
8311                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8312         }
8313
8314         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8315                 PlaneClassify(r_refdef.view.frustum + i);
8316
8317         // LordHavoc: note to all quake engine coders, Quake had a special case
8318         // for 90 degrees which assumed a square view (wrong), so I removed it,
8319         // Quake2 has it disabled as well.
8320
8321         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8322         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8323         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8324         //PlaneClassify(&frustum[0]);
8325
8326         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8327         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8328         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8329         //PlaneClassify(&frustum[1]);
8330
8331         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8332         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8333         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8334         //PlaneClassify(&frustum[2]);
8335
8336         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8337         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8338         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8339         //PlaneClassify(&frustum[3]);
8340
8341         // nearclip plane
8342         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8343         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8344         //PlaneClassify(&frustum[4]);
8345 }
8346
8347 void R_View_UpdateWithScissor(const int *myscissor)
8348 {
8349         R_Main_ResizeViewCache();
8350         R_View_SetFrustum(myscissor);
8351         R_View_WorldVisibility(r_refdef.view.useclipplane);
8352         R_View_UpdateEntityVisible();
8353         R_View_UpdateEntityLighting();
8354 }
8355
8356 void R_View_Update(void)
8357 {
8358         R_Main_ResizeViewCache();
8359         R_View_SetFrustum(NULL);
8360         R_View_WorldVisibility(r_refdef.view.useclipplane);
8361         R_View_UpdateEntityVisible();
8362         R_View_UpdateEntityLighting();
8363 }
8364
8365 void R_SetupView(qboolean allowwaterclippingplane)
8366 {
8367         const float *customclipplane = NULL;
8368         float plane[4];
8369         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8370         {
8371                 // LordHavoc: couldn't figure out how to make this approach the
8372                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8373                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8374                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8375                         dist = r_refdef.view.clipplane.dist;
8376                 plane[0] = r_refdef.view.clipplane.normal[0];
8377                 plane[1] = r_refdef.view.clipplane.normal[1];
8378                 plane[2] = r_refdef.view.clipplane.normal[2];
8379                 plane[3] = dist;
8380                 customclipplane = plane;
8381         }
8382
8383         if (!r_refdef.view.useperspective)
8384                 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);
8385         else if (vid.stencil && r_useinfinitefarclip.integer)
8386                 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);
8387         else
8388                 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);
8389         R_SetViewport(&r_refdef.view.viewport);
8390 }
8391
8392 void R_EntityMatrix(const matrix4x4_t *matrix)
8393 {
8394         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8395         {
8396                 gl_modelmatrixchanged = false;
8397                 gl_modelmatrix = *matrix;
8398                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8399                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8400                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8401                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8402                 CHECKGLERROR
8403                 switch(vid.renderpath)
8404                 {
8405                 case RENDERPATH_D3D9:
8406 #ifdef SUPPORTD3D
8407                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8408                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8409 #endif
8410                         break;
8411                 case RENDERPATH_D3D10:
8412                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8413                         break;
8414                 case RENDERPATH_D3D11:
8415                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8416                         break;
8417                 case RENDERPATH_GL20:
8418                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8419                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8420                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8421                         break;
8422                 case RENDERPATH_CGGL:
8423 #ifdef SUPPORTCG
8424                         CHECKCGERROR
8425                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8426                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8427                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8428 #endif
8429                         break;
8430                 case RENDERPATH_GL13:
8431                 case RENDERPATH_GL11:
8432                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8433                         break;
8434                 }
8435         }
8436 }
8437
8438 void R_ResetViewRendering2D(void)
8439 {
8440         r_viewport_t viewport;
8441         DrawQ_Finish();
8442
8443         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8444         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);
8445         R_SetViewport(&viewport);
8446         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8447         GL_Color(1, 1, 1, 1);
8448         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8449         GL_BlendFunc(GL_ONE, GL_ZERO);
8450         GL_AlphaTest(false);
8451         GL_ScissorTest(false);
8452         GL_DepthMask(false);
8453         GL_DepthRange(0, 1);
8454         GL_DepthTest(false);
8455         GL_DepthFunc(GL_LEQUAL);
8456         R_EntityMatrix(&identitymatrix);
8457         R_Mesh_ResetTextureState();
8458         GL_PolygonOffset(0, 0);
8459         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8460         switch(vid.renderpath)
8461         {
8462         case RENDERPATH_GL11:
8463         case RENDERPATH_GL13:
8464         case RENDERPATH_GL20:
8465         case RENDERPATH_CGGL:
8466                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8467                 break;
8468         case RENDERPATH_D3D9:
8469         case RENDERPATH_D3D10:
8470         case RENDERPATH_D3D11:
8471                 break;
8472         }
8473         GL_CullFace(GL_NONE);
8474 }
8475
8476 void R_ResetViewRendering3D(void)
8477 {
8478         DrawQ_Finish();
8479
8480         R_SetupView(true);
8481         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8482         GL_Color(1, 1, 1, 1);
8483         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8484         GL_BlendFunc(GL_ONE, GL_ZERO);
8485         GL_AlphaTest(false);
8486         GL_ScissorTest(true);
8487         GL_DepthMask(true);
8488         GL_DepthRange(0, 1);
8489         GL_DepthTest(true);
8490         GL_DepthFunc(GL_LEQUAL);
8491         R_EntityMatrix(&identitymatrix);
8492         R_Mesh_ResetTextureState();
8493         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8494         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8495         switch(vid.renderpath)
8496         {
8497         case RENDERPATH_GL11:
8498         case RENDERPATH_GL13:
8499         case RENDERPATH_GL20:
8500         case RENDERPATH_CGGL:
8501                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8502                 break;
8503         case RENDERPATH_D3D9:
8504         case RENDERPATH_D3D10:
8505         case RENDERPATH_D3D11:
8506                 break;
8507         }
8508         GL_CullFace(r_refdef.view.cullface_back);
8509 }
8510
8511 /*
8512 ================
8513 R_RenderView_UpdateViewVectors
8514 ================
8515 */
8516 static void R_RenderView_UpdateViewVectors(void)
8517 {
8518         // break apart the view matrix into vectors for various purposes
8519         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8520         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8521         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8522         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8523         // make an inverted copy of the view matrix for tracking sprites
8524         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8525 }
8526
8527 void R_RenderScene(void);
8528 void R_RenderWaterPlanes(void);
8529
8530 static void R_Water_StartFrame(void)
8531 {
8532         int i;
8533         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8534         r_waterstate_waterplane_t *p;
8535
8536         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8537                 return;
8538
8539         switch(vid.renderpath)
8540         {
8541         case RENDERPATH_GL20:
8542         case RENDERPATH_CGGL:
8543         case RENDERPATH_D3D9:
8544         case RENDERPATH_D3D10:
8545         case RENDERPATH_D3D11:
8546                 break;
8547         case RENDERPATH_GL13:
8548         case RENDERPATH_GL11:
8549                 return;
8550         }
8551
8552         // set waterwidth and waterheight to the water resolution that will be
8553         // used (often less than the screen resolution for faster rendering)
8554         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8555         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8556
8557         // calculate desired texture sizes
8558         // can't use water if the card does not support the texture size
8559         if (!r_water.integer || r_showsurfaces.integer)
8560                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8561         else if (vid.support.arb_texture_non_power_of_two)
8562         {
8563                 texturewidth = waterwidth;
8564                 textureheight = waterheight;
8565                 camerawidth = waterwidth;
8566                 cameraheight = waterheight;
8567         }
8568         else
8569         {
8570                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8571                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8572                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8573                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8574         }
8575
8576         // allocate textures as needed
8577         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8578         {
8579                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8580                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8581                 {
8582                         if (p->texture_refraction)
8583                                 R_FreeTexture(p->texture_refraction);
8584                         p->texture_refraction = NULL;
8585                         if (p->texture_reflection)
8586                                 R_FreeTexture(p->texture_reflection);
8587                         p->texture_reflection = NULL;
8588                         if (p->texture_camera)
8589                                 R_FreeTexture(p->texture_camera);
8590                         p->texture_camera = NULL;
8591                 }
8592                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8593                 r_waterstate.texturewidth = texturewidth;
8594                 r_waterstate.textureheight = textureheight;
8595                 r_waterstate.camerawidth = camerawidth;
8596                 r_waterstate.cameraheight = cameraheight;
8597         }
8598
8599         if (r_waterstate.texturewidth)
8600         {
8601                 r_waterstate.enabled = true;
8602
8603                 // when doing a reduced render (HDR) we want to use a smaller area
8604                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8605                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8606
8607                 // set up variables that will be used in shader setup
8608                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8609                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8610                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8611                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8612         }
8613
8614         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8615         r_waterstate.numwaterplanes = 0;
8616 }
8617
8618 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8619 {
8620         int triangleindex, planeindex;
8621         const int *e;
8622         vec3_t vert[3];
8623         vec3_t normal;
8624         vec3_t center;
8625         mplane_t plane;
8626         r_waterstate_waterplane_t *p;
8627         texture_t *t = R_GetCurrentTexture(surface->texture);
8628
8629         // just use the first triangle with a valid normal for any decisions
8630         VectorClear(normal);
8631         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8632         {
8633                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8634                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8635                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8636                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8637                 if (VectorLength2(normal) >= 0.001)
8638                         break;
8639         }
8640
8641         VectorCopy(normal, plane.normal);
8642         VectorNormalize(plane.normal);
8643         plane.dist = DotProduct(vert[0], plane.normal);
8644         PlaneClassify(&plane);
8645         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8646         {
8647                 // skip backfaces (except if nocullface is set)
8648                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8649                         return;
8650                 VectorNegate(plane.normal, plane.normal);
8651                 plane.dist *= -1;
8652                 PlaneClassify(&plane);
8653         }
8654
8655
8656         // find a matching plane if there is one
8657         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8658                 if(p->camera_entity == t->camera_entity)
8659                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8660                                 break;
8661         if (planeindex >= r_waterstate.maxwaterplanes)
8662                 return; // nothing we can do, out of planes
8663
8664         // if this triangle does not fit any known plane rendered this frame, add one
8665         if (planeindex >= r_waterstate.numwaterplanes)
8666         {
8667                 // store the new plane
8668                 r_waterstate.numwaterplanes++;
8669                 p->plane = plane;
8670                 // clear materialflags and pvs
8671                 p->materialflags = 0;
8672                 p->pvsvalid = false;
8673                 p->camera_entity = t->camera_entity;
8674                 VectorCopy(surface->mins, p->mins);
8675                 VectorCopy(surface->maxs, p->maxs);
8676         }
8677         else
8678         {
8679                 // merge mins/maxs
8680                 p->mins[0] = min(p->mins[0], surface->mins[0]);
8681                 p->mins[1] = min(p->mins[1], surface->mins[1]);
8682                 p->mins[2] = min(p->mins[2], surface->mins[2]);
8683                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8684                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8685                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8686         }
8687         // merge this surface's materialflags into the waterplane
8688         p->materialflags |= t->currentmaterialflags;
8689         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8690         {
8691                 // merge this surface's PVS into the waterplane
8692                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8693                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8694                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8695                 {
8696                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8697                         p->pvsvalid = true;
8698                 }
8699         }
8700 }
8701
8702 static void R_Water_ProcessPlanes(void)
8703 {
8704         int myscissor[4];
8705         r_refdef_view_t originalview;
8706         r_refdef_view_t myview;
8707         int planeindex;
8708         r_waterstate_waterplane_t *p;
8709         vec3_t visorigin;
8710
8711         originalview = r_refdef.view;
8712
8713         // make sure enough textures are allocated
8714         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8715         {
8716                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8717                 {
8718                         if (!p->texture_refraction)
8719                                 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);
8720                         if (!p->texture_refraction)
8721                                 goto error;
8722                 }
8723                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8724                 {
8725                         if (!p->texture_camera)
8726                                 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);
8727                         if (!p->texture_camera)
8728                                 goto error;
8729                 }
8730
8731                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8732                 {
8733                         if (!p->texture_reflection)
8734                                 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);
8735                         if (!p->texture_reflection)
8736                                 goto error;
8737                 }
8738         }
8739
8740         // render views
8741         r_refdef.view = originalview;
8742         r_refdef.view.showdebug = false;
8743         r_refdef.view.width = r_waterstate.waterwidth;
8744         r_refdef.view.height = r_waterstate.waterheight;
8745         r_refdef.view.useclipplane = true;
8746         myview = r_refdef.view;
8747         r_waterstate.renderingscene = true;
8748         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8749         {
8750                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8751                 {
8752                         r_refdef.view = myview;
8753                         if(r_water_scissormode.integer)
8754                         {
8755                                 R_SetupView(true);
8756                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8757                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8758                         }
8759
8760                         // render reflected scene and copy into texture
8761                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8762                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8763                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8764                         r_refdef.view.clipplane = p->plane;
8765
8766                         // reverse the cullface settings for this render
8767                         r_refdef.view.cullface_front = GL_FRONT;
8768                         r_refdef.view.cullface_back = GL_BACK;
8769                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8770                         {
8771                                 r_refdef.view.usecustompvs = true;
8772                                 if (p->pvsvalid)
8773                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8774                                 else
8775                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8776                         }
8777
8778                         R_ResetViewRendering3D();
8779                         R_ClearScreen(r_refdef.fogenabled);
8780                         if(r_water_scissormode.integer & 2)
8781                                 R_View_UpdateWithScissor(myscissor);
8782                         else
8783                                 R_View_Update();
8784                         if(r_water_scissormode.integer & 1)
8785                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8786                         R_RenderScene();
8787
8788                         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);
8789                 }
8790
8791                 // render the normal view scene and copy into texture
8792                 // (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)
8793                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8794                 {
8795                         r_refdef.view = myview;
8796                         if(r_water_scissormode.integer)
8797                         {
8798                                 R_SetupView(true);
8799                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8800                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8801                         }
8802
8803                         r_waterstate.renderingrefraction = true;
8804
8805                         r_refdef.view.clipplane = p->plane;
8806                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8807                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8808
8809                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8810                         {
8811                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8812                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8813                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8814                                 R_RenderView_UpdateViewVectors();
8815                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8816                                 {
8817                                         r_refdef.view.usecustompvs = true;
8818                                         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);
8819                                 }
8820                         }
8821
8822                         PlaneClassify(&r_refdef.view.clipplane);
8823
8824                         R_ResetViewRendering3D();
8825                         R_ClearScreen(r_refdef.fogenabled);
8826                         if(r_water_scissormode.integer & 2)
8827                                 R_View_UpdateWithScissor(myscissor);
8828                         else
8829                                 R_View_Update();
8830                         if(r_water_scissormode.integer & 1)
8831                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8832                         R_RenderScene();
8833
8834                         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);
8835                         r_waterstate.renderingrefraction = false;
8836                 }
8837                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8838                 {
8839                         r_refdef.view = myview;
8840
8841                         r_refdef.view.clipplane = p->plane;
8842                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8843                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8844
8845                         r_refdef.view.width = r_waterstate.camerawidth;
8846                         r_refdef.view.height = r_waterstate.cameraheight;
8847                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8848                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8849
8850                         if(p->camera_entity)
8851                         {
8852                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8853                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8854                         }
8855
8856                         // note: all of the view is used for displaying... so
8857                         // there is no use in scissoring
8858
8859                         // reverse the cullface settings for this render
8860                         r_refdef.view.cullface_front = GL_FRONT;
8861                         r_refdef.view.cullface_back = GL_BACK;
8862                         // also reverse the view matrix
8863                         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
8864                         R_RenderView_UpdateViewVectors();
8865                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8866                         {
8867                                 r_refdef.view.usecustompvs = true;
8868                                 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);
8869                         }
8870                         
8871                         // camera needs no clipplane
8872                         r_refdef.view.useclipplane = false;
8873
8874                         PlaneClassify(&r_refdef.view.clipplane);
8875
8876                         R_ResetViewRendering3D();
8877                         R_ClearScreen(r_refdef.fogenabled);
8878                         R_View_Update();
8879                         R_RenderScene();
8880
8881                         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);
8882                         r_waterstate.renderingrefraction = false;
8883                 }
8884
8885         }
8886         r_waterstate.renderingscene = false;
8887         r_refdef.view = originalview;
8888         R_ResetViewRendering3D();
8889         R_ClearScreen(r_refdef.fogenabled);
8890         R_View_Update();
8891         return;
8892 error:
8893         r_refdef.view = originalview;
8894         r_waterstate.renderingscene = false;
8895         Cvar_SetValueQuick(&r_water, 0);
8896         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8897         return;
8898 }
8899
8900 void R_Bloom_StartFrame(void)
8901 {
8902         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8903
8904         switch(vid.renderpath)
8905         {
8906         case RENDERPATH_GL20:
8907         case RENDERPATH_CGGL:
8908         case RENDERPATH_D3D9:
8909         case RENDERPATH_D3D10:
8910         case RENDERPATH_D3D11:
8911                 break;
8912         case RENDERPATH_GL13:
8913         case RENDERPATH_GL11:
8914                 return;
8915         }
8916
8917         // set bloomwidth and bloomheight to the bloom resolution that will be
8918         // used (often less than the screen resolution for faster rendering)
8919         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8920         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8921         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8922         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8923         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8924
8925         // calculate desired texture sizes
8926         if (vid.support.arb_texture_non_power_of_two)
8927         {
8928                 screentexturewidth = r_refdef.view.width;
8929                 screentextureheight = r_refdef.view.height;
8930                 bloomtexturewidth = r_bloomstate.bloomwidth;
8931                 bloomtextureheight = r_bloomstate.bloomheight;
8932         }
8933         else
8934         {
8935                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8936                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8937                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8938                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8939         }
8940
8941         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))
8942         {
8943                 Cvar_SetValueQuick(&r_hdr, 0);
8944                 Cvar_SetValueQuick(&r_bloom, 0);
8945                 Cvar_SetValueQuick(&r_motionblur, 0);
8946                 Cvar_SetValueQuick(&r_damageblur, 0);
8947         }
8948
8949         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)))
8950                 screentexturewidth = screentextureheight = 0;
8951         if (!r_hdr.integer && !r_bloom.integer)
8952                 bloomtexturewidth = bloomtextureheight = 0;
8953
8954         // allocate textures as needed
8955         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8956         {
8957                 if (r_bloomstate.texture_screen)
8958                         R_FreeTexture(r_bloomstate.texture_screen);
8959                 r_bloomstate.texture_screen = NULL;
8960                 r_bloomstate.screentexturewidth = screentexturewidth;
8961                 r_bloomstate.screentextureheight = screentextureheight;
8962                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8963                         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);
8964         }
8965         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8966         {
8967                 if (r_bloomstate.texture_bloom)
8968                         R_FreeTexture(r_bloomstate.texture_bloom);
8969                 r_bloomstate.texture_bloom = NULL;
8970                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8971                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8972                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8973                         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);
8974         }
8975
8976         // when doing a reduced render (HDR) we want to use a smaller area
8977         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8978         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8979         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8980         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8981         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8982
8983         // set up a texcoord array for the full resolution screen image
8984         // (we have to keep this around to copy back during final render)
8985         r_bloomstate.screentexcoord2f[0] = 0;
8986         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8987         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8988         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8989         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8990         r_bloomstate.screentexcoord2f[5] = 0;
8991         r_bloomstate.screentexcoord2f[6] = 0;
8992         r_bloomstate.screentexcoord2f[7] = 0;
8993
8994         // set up a texcoord array for the reduced resolution bloom image
8995         // (which will be additive blended over the screen image)
8996         r_bloomstate.bloomtexcoord2f[0] = 0;
8997         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8998         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8999         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9000         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9001         r_bloomstate.bloomtexcoord2f[5] = 0;
9002         r_bloomstate.bloomtexcoord2f[6] = 0;
9003         r_bloomstate.bloomtexcoord2f[7] = 0;
9004
9005         switch(vid.renderpath)
9006         {
9007         case RENDERPATH_GL11:
9008         case RENDERPATH_GL13:
9009         case RENDERPATH_GL20:
9010         case RENDERPATH_CGGL:
9011                 break;
9012         case RENDERPATH_D3D9:
9013         case RENDERPATH_D3D10:
9014         case RENDERPATH_D3D11:
9015                 {
9016                         int i;
9017                         for (i = 0;i < 4;i++)
9018                         {
9019                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
9020                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
9021                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
9022                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
9023                         }
9024                 }
9025                 break;
9026         }
9027
9028         if (r_hdr.integer || r_bloom.integer)
9029         {
9030                 r_bloomstate.enabled = true;
9031                 r_bloomstate.hdr = r_hdr.integer != 0;
9032         }
9033
9034         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);
9035 }
9036
9037 void R_Bloom_CopyBloomTexture(float colorscale)
9038 {
9039         r_refdef.stats.bloom++;
9040
9041         // scale down screen texture to the bloom texture size
9042         CHECKGLERROR
9043         R_SetViewport(&r_bloomstate.viewport);
9044         GL_BlendFunc(GL_ONE, GL_ZERO);
9045         GL_Color(colorscale, colorscale, colorscale, 1);
9046         // 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...
9047         switch(vid.renderpath)
9048         {
9049         case RENDERPATH_GL11:
9050         case RENDERPATH_GL13:
9051         case RENDERPATH_GL20:
9052         case RENDERPATH_CGGL:
9053                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9054                 break;
9055         case RENDERPATH_D3D9:
9056         case RENDERPATH_D3D10:
9057         case RENDERPATH_D3D11:
9058                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9059                 break;
9060         }
9061         // TODO: do boxfilter scale-down in shader?
9062         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9063         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9064         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9065
9066         // we now have a bloom image in the framebuffer
9067         // copy it into the bloom image texture for later processing
9068         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);
9069         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9070 }
9071
9072 void R_Bloom_CopyHDRTexture(void)
9073 {
9074         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);
9075         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9076 }
9077
9078 void R_Bloom_MakeTexture(void)
9079 {
9080         int x, range, dir;
9081         float xoffset, yoffset, r, brighten;
9082
9083         r_refdef.stats.bloom++;
9084
9085         R_ResetViewRendering2D();
9086
9087         // we have a bloom image in the framebuffer
9088         CHECKGLERROR
9089         R_SetViewport(&r_bloomstate.viewport);
9090
9091         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9092         {
9093                 x *= 2;
9094                 r = bound(0, r_bloom_colorexponent.value / x, 1);
9095                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9096                 GL_Color(r,r,r,1);
9097                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9098                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9099                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9100                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9101
9102                 // copy the vertically blurred bloom view to a texture
9103                 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);
9104                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9105         }
9106
9107         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9108         brighten = r_bloom_brighten.value;
9109         if (r_hdr.integer)
9110                 brighten *= r_hdr_range.value;
9111         brighten = sqrt(brighten);
9112         if(range >= 1)
9113                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9114         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9115
9116         for (dir = 0;dir < 2;dir++)
9117         {
9118                 // blend on at multiple vertical offsets to achieve a vertical blur
9119                 // TODO: do offset blends using GLSL
9120                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9121                 GL_BlendFunc(GL_ONE, GL_ZERO);
9122                 for (x = -range;x <= range;x++)
9123                 {
9124                         if (!dir){xoffset = 0;yoffset = x;}
9125                         else {xoffset = x;yoffset = 0;}
9126                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
9127                         yoffset /= (float)r_bloomstate.bloomtextureheight;
9128                         // compute a texcoord array with the specified x and y offset
9129                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9130                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9131                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9132                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9133                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9134                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9135                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9136                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9137                         // this r value looks like a 'dot' particle, fading sharply to
9138                         // black at the edges
9139                         // (probably not realistic but looks good enough)
9140                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9141                         //r = brighten/(range*2+1);
9142                         r = brighten / (range * 2 + 1);
9143                         if(range >= 1)
9144                                 r *= (1 - x*x/(float)(range*range));
9145                         GL_Color(r, r, r, 1);
9146                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9147                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9148                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9149                         GL_BlendFunc(GL_ONE, GL_ONE);
9150                 }
9151
9152                 // copy the vertically blurred bloom view to a texture
9153                 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);
9154                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9155         }
9156 }
9157
9158 void R_HDR_RenderBloomTexture(void)
9159 {
9160         int oldwidth, oldheight;
9161         float oldcolorscale;
9162
9163         oldcolorscale = r_refdef.view.colorscale;
9164         oldwidth = r_refdef.view.width;
9165         oldheight = r_refdef.view.height;
9166         r_refdef.view.width = r_bloomstate.bloomwidth;
9167         r_refdef.view.height = r_bloomstate.bloomheight;
9168
9169         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
9170         // TODO: add exposure compensation features
9171         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9172
9173         r_refdef.view.showdebug = false;
9174         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9175
9176         R_ResetViewRendering3D();
9177
9178         R_ClearScreen(r_refdef.fogenabled);
9179         if (r_timereport_active)
9180                 R_TimeReport("HDRclear");
9181
9182         R_View_Update();
9183         if (r_timereport_active)
9184                 R_TimeReport("visibility");
9185
9186         // only do secondary renders with HDR if r_hdr is 2 or higher
9187         r_waterstate.numwaterplanes = 0;
9188         if (r_waterstate.enabled && r_hdr.integer >= 2)
9189                 R_RenderWaterPlanes();
9190
9191         r_refdef.view.showdebug = true;
9192         R_RenderScene();
9193         r_waterstate.numwaterplanes = 0;
9194
9195         R_ResetViewRendering2D();
9196
9197         R_Bloom_CopyHDRTexture();
9198         R_Bloom_MakeTexture();
9199
9200         // restore the view settings
9201         r_refdef.view.width = oldwidth;
9202         r_refdef.view.height = oldheight;
9203         r_refdef.view.colorscale = oldcolorscale;
9204
9205         R_ResetViewRendering3D();
9206
9207         R_ClearScreen(r_refdef.fogenabled);
9208         if (r_timereport_active)
9209                 R_TimeReport("viewclear");
9210 }
9211
9212 static void R_BlendView(void)
9213 {
9214         unsigned int permutation;
9215         float uservecs[4][4];
9216
9217         switch (vid.renderpath)
9218         {
9219         case RENDERPATH_GL20:
9220         case RENDERPATH_CGGL:
9221         case RENDERPATH_D3D9:
9222         case RENDERPATH_D3D10:
9223         case RENDERPATH_D3D11:
9224                 permutation =
9225                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9226                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9227                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9228                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9229                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9230
9231                 if (r_bloomstate.texture_screen)
9232                 {
9233                         // make sure the buffer is available
9234                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9235
9236                         R_ResetViewRendering2D();
9237
9238                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9239                         {
9240                                 // declare variables
9241                                 float speed;
9242                                 static float avgspeed;
9243
9244                                 speed = VectorLength(cl.movement_velocity);
9245
9246                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9247                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9248
9249                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9250                                 speed = bound(0, speed, 1);
9251                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9252
9253                                 // calculate values into a standard alpha
9254                                 cl.motionbluralpha = 1 - exp(-
9255                                                 (
9256                                                  (r_motionblur.value * speed / 80)
9257                                                  +
9258                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9259                                                 )
9260                                                 /
9261                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
9262                                            );
9263
9264                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9265                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9266                                 // apply the blur
9267                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9268                                 {
9269                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9270                                         GL_Color(1, 1, 1, cl.motionbluralpha);
9271                                         switch(vid.renderpath)
9272                                         {
9273                                         case RENDERPATH_GL11:
9274                                         case RENDERPATH_GL13:
9275                                         case RENDERPATH_GL20:
9276                                         case RENDERPATH_CGGL:
9277                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9278                                                 break;
9279                                         case RENDERPATH_D3D9:
9280                                         case RENDERPATH_D3D10:
9281                                         case RENDERPATH_D3D11:
9282                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9283                                                 break;
9284                                         }
9285                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9286                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9287                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9288                                 }
9289                         }
9290
9291                         // copy view into the screen texture
9292                         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);
9293                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9294                 }
9295                 else if (!r_bloomstate.texture_bloom)
9296                 {
9297                         // we may still have to do view tint...
9298                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9299                         {
9300                                 // apply a color tint to the whole view
9301                                 R_ResetViewRendering2D();
9302                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9303                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9304                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9305                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9306                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9307                         }
9308                         break; // no screen processing, no bloom, skip it
9309                 }
9310
9311                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9312                 {
9313                         // render simple bloom effect
9314                         // copy the screen and shrink it and darken it for the bloom process
9315                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9316                         // make the bloom texture
9317                         R_Bloom_MakeTexture();
9318                 }
9319
9320 #if _MSC_VER >= 1400
9321 #define sscanf sscanf_s
9322 #endif
9323                 memset(uservecs, 0, sizeof(uservecs));
9324                 if (r_glsl_postprocess_uservec1_enable.integer)
9325                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9326                 if (r_glsl_postprocess_uservec2_enable.integer)
9327                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9328                 if (r_glsl_postprocess_uservec3_enable.integer)
9329                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9330                 if (r_glsl_postprocess_uservec4_enable.integer)
9331                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9332
9333                 R_ResetViewRendering2D();
9334                 GL_Color(1, 1, 1, 1);
9335                 GL_BlendFunc(GL_ONE, GL_ZERO);
9336
9337                 switch(vid.renderpath)
9338                 {
9339                 case RENDERPATH_GL20:
9340                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9341                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9342                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9343                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9344                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9345                         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]);
9346                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9347                         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]);
9348                         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]);
9349                         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]);
9350                         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]);
9351                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9352                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9353                         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);
9354                         break;
9355                 case RENDERPATH_CGGL:
9356 #ifdef SUPPORTCG
9357                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9358                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9359                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9360                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9361                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9362                         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
9363                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9364                         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
9365                         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
9366                         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
9367                         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
9368                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9369                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9370                         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);
9371 #endif
9372                         break;
9373                 case RENDERPATH_D3D9:
9374 #ifdef SUPPORTD3D
9375                         // 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...
9376                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9377                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9378                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9379                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9380                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9381                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9382                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9383                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9384                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9385                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9386                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9387                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9388                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9389                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9390 #endif
9391                         break;
9392                 case RENDERPATH_D3D10:
9393                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9394                         break;
9395                 case RENDERPATH_D3D11:
9396                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9397                         break;
9398                 default:
9399                         break;
9400                 }
9401                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9402                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9403                 break;
9404         case RENDERPATH_GL13:
9405         case RENDERPATH_GL11:
9406                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9407                 {
9408                         // apply a color tint to the whole view
9409                         R_ResetViewRendering2D();
9410                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9411                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9412                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9413                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9414                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9415                 }
9416                 break;
9417         }
9418 }
9419
9420 matrix4x4_t r_waterscrollmatrix;
9421
9422 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9423 {
9424         if (r_refdef.fog_density)
9425         {
9426                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9427                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9428                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9429
9430                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9431                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9432                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9433                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9434
9435                 {
9436                         vec3_t fogvec;
9437                         VectorCopy(r_refdef.fogcolor, fogvec);
9438                         //   color.rgb *= ContrastBoost * SceneBrightness;
9439                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9440                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9441                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9442                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9443                 }
9444         }
9445 }
9446
9447 void R_UpdateVariables(void)
9448 {
9449         R_Textures_Frame();
9450
9451         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9452
9453         r_refdef.farclip = r_farclip_base.value;
9454         if (r_refdef.scene.worldmodel)
9455                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9456         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9457
9458         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9459                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9460         r_refdef.polygonfactor = 0;
9461         r_refdef.polygonoffset = 0;
9462         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9463         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9464
9465         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9466         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9467         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9468         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9469         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9470         if (FAKELIGHT_ENABLED)
9471         {
9472                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9473         }
9474         if (r_showsurfaces.integer)
9475         {
9476                 r_refdef.scene.rtworld = false;
9477                 r_refdef.scene.rtworldshadows = false;
9478                 r_refdef.scene.rtdlight = false;
9479                 r_refdef.scene.rtdlightshadows = false;
9480                 r_refdef.lightmapintensity = 0;
9481         }
9482
9483         if (gamemode == GAME_NEHAHRA)
9484         {
9485                 if (gl_fogenable.integer)
9486                 {
9487                         r_refdef.oldgl_fogenable = true;
9488                         r_refdef.fog_density = gl_fogdensity.value;
9489                         r_refdef.fog_red = gl_fogred.value;
9490                         r_refdef.fog_green = gl_foggreen.value;
9491                         r_refdef.fog_blue = gl_fogblue.value;
9492                         r_refdef.fog_alpha = 1;
9493                         r_refdef.fog_start = 0;
9494                         r_refdef.fog_end = gl_skyclip.value;
9495                         r_refdef.fog_height = 1<<30;
9496                         r_refdef.fog_fadedepth = 128;
9497                 }
9498                 else if (r_refdef.oldgl_fogenable)
9499                 {
9500                         r_refdef.oldgl_fogenable = false;
9501                         r_refdef.fog_density = 0;
9502                         r_refdef.fog_red = 0;
9503                         r_refdef.fog_green = 0;
9504                         r_refdef.fog_blue = 0;
9505                         r_refdef.fog_alpha = 0;
9506                         r_refdef.fog_start = 0;
9507                         r_refdef.fog_end = 0;
9508                         r_refdef.fog_height = 1<<30;
9509                         r_refdef.fog_fadedepth = 128;
9510                 }
9511         }
9512
9513         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9514         r_refdef.fog_start = max(0, r_refdef.fog_start);
9515         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9516
9517         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9518
9519         if (r_refdef.fog_density && r_drawfog.integer)
9520         {
9521                 r_refdef.fogenabled = true;
9522                 // this is the point where the fog reaches 0.9986 alpha, which we
9523                 // consider a good enough cutoff point for the texture
9524                 // (0.9986 * 256 == 255.6)
9525                 if (r_fog_exp2.integer)
9526                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9527                 else
9528                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9529                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9530                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9531                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9532                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9533                         R_BuildFogHeightTexture();
9534                 // fog color was already set
9535                 // update the fog texture
9536                 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)
9537                         R_BuildFogTexture();
9538                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9539                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9540         }
9541         else
9542                 r_refdef.fogenabled = false;
9543
9544         switch(vid.renderpath)
9545         {
9546         case RENDERPATH_GL20:
9547         case RENDERPATH_CGGL:
9548         case RENDERPATH_D3D9:
9549         case RENDERPATH_D3D10:
9550         case RENDERPATH_D3D11:
9551                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9552                 {
9553                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9554                         {
9555                                 // build GLSL gamma texture
9556 #define RAMPWIDTH 256
9557                                 unsigned short ramp[RAMPWIDTH * 3];
9558                                 unsigned char rampbgr[RAMPWIDTH][4];
9559                                 int i;
9560
9561                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9562
9563                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9564                                 for(i = 0; i < RAMPWIDTH; ++i)
9565                                 {
9566                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9567                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9568                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9569                                         rampbgr[i][3] = 0;
9570                                 }
9571                                 if (r_texture_gammaramps)
9572                                 {
9573                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9574                                 }
9575                                 else
9576                                 {
9577                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9578                                 }
9579                         }
9580                 }
9581                 else
9582                 {
9583                         // remove GLSL gamma texture
9584                 }
9585                 break;
9586         case RENDERPATH_GL13:
9587         case RENDERPATH_GL11:
9588                 break;
9589         }
9590 }
9591
9592 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9593 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9594 /*
9595 ================
9596 R_SelectScene
9597 ================
9598 */
9599 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9600         if( scenetype != r_currentscenetype ) {
9601                 // store the old scenetype
9602                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9603                 r_currentscenetype = scenetype;
9604                 // move in the new scene
9605                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9606         }
9607 }
9608
9609 /*
9610 ================
9611 R_GetScenePointer
9612 ================
9613 */
9614 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9615 {
9616         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9617         if( scenetype == r_currentscenetype ) {
9618                 return &r_refdef.scene;
9619         } else {
9620                 return &r_scenes_store[ scenetype ];
9621         }
9622 }
9623
9624 /*
9625 ================
9626 R_RenderView
9627 ================
9628 */
9629 void R_RenderView(void)
9630 {
9631         if (r_timereport_active)
9632                 R_TimeReport("start");
9633         r_textureframe++; // used only by R_GetCurrentTexture
9634         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9635
9636         if(R_CompileShader_CheckStaticParms())
9637                 R_GLSL_Restart_f();
9638
9639         if (!r_drawentities.integer)
9640                 r_refdef.scene.numentities = 0;
9641
9642         R_AnimCache_ClearCache();
9643         R_FrameData_NewFrame();
9644
9645         if (r_refdef.view.isoverlay)
9646         {
9647                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9648                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9649                 R_TimeReport("depthclear");
9650
9651                 r_refdef.view.showdebug = false;
9652
9653                 r_waterstate.enabled = false;
9654                 r_waterstate.numwaterplanes = 0;
9655
9656                 R_RenderScene();
9657
9658                 CHECKGLERROR
9659                 return;
9660         }
9661
9662         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9663                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9664
9665         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9666
9667         R_RenderView_UpdateViewVectors();
9668
9669         R_Shadow_UpdateWorldLightSelection();
9670
9671         R_Bloom_StartFrame();
9672         R_Water_StartFrame();
9673
9674         CHECKGLERROR
9675         if (r_timereport_active)
9676                 R_TimeReport("viewsetup");
9677
9678         R_ResetViewRendering3D();
9679
9680         if (r_refdef.view.clear || r_refdef.fogenabled)
9681         {
9682                 R_ClearScreen(r_refdef.fogenabled);
9683                 if (r_timereport_active)
9684                         R_TimeReport("viewclear");
9685         }
9686         r_refdef.view.clear = true;
9687
9688         // this produces a bloom texture to be used in R_BlendView() later
9689         if (r_hdr.integer && r_bloomstate.bloomwidth)
9690         {
9691                 R_HDR_RenderBloomTexture();
9692                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9693                 r_textureframe++; // used only by R_GetCurrentTexture
9694         }
9695
9696         r_refdef.view.showdebug = true;
9697
9698         R_View_Update();
9699         if (r_timereport_active)
9700                 R_TimeReport("visibility");
9701
9702         r_waterstate.numwaterplanes = 0;
9703         if (r_waterstate.enabled)
9704                 R_RenderWaterPlanes();
9705
9706         R_RenderScene();
9707         r_waterstate.numwaterplanes = 0;
9708
9709         R_BlendView();
9710         if (r_timereport_active)
9711                 R_TimeReport("blendview");
9712
9713         GL_Scissor(0, 0, vid.width, vid.height);
9714         GL_ScissorTest(false);
9715
9716         CHECKGLERROR
9717 }
9718
9719 void R_RenderWaterPlanes(void)
9720 {
9721         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9722         {
9723                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9724                 if (r_timereport_active)
9725                         R_TimeReport("waterworld");
9726         }
9727
9728         // don't let sound skip if going slow
9729         if (r_refdef.scene.extraupdate)
9730                 S_ExtraUpdate ();
9731
9732         R_DrawModelsAddWaterPlanes();
9733         if (r_timereport_active)
9734                 R_TimeReport("watermodels");
9735
9736         if (r_waterstate.numwaterplanes)
9737         {
9738                 R_Water_ProcessPlanes();
9739                 if (r_timereport_active)
9740                         R_TimeReport("waterscenes");
9741         }
9742 }
9743
9744 extern void R_DrawLightningBeams (void);
9745 extern void VM_CL_AddPolygonsToMeshQueue (void);
9746 extern void R_DrawPortals (void);
9747 extern cvar_t cl_locs_show;
9748 static void R_DrawLocs(void);
9749 static void R_DrawEntityBBoxes(void);
9750 static void R_DrawModelDecals(void);
9751 extern void R_DrawModelShadows(void);
9752 extern void R_DrawModelShadowMaps(void);
9753 extern cvar_t cl_decals_newsystem;
9754 extern qboolean r_shadow_usingdeferredprepass;
9755 void R_RenderScene(void)
9756 {
9757         qboolean shadowmapping = false;
9758
9759         if (r_timereport_active)
9760                 R_TimeReport("beginscene");
9761
9762         r_refdef.stats.renders++;
9763
9764         R_UpdateFogColor();
9765
9766         // don't let sound skip if going slow
9767         if (r_refdef.scene.extraupdate)
9768                 S_ExtraUpdate ();
9769
9770         R_MeshQueue_BeginScene();
9771
9772         R_SkyStartFrame();
9773
9774         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);
9775
9776         if (r_timereport_active)
9777                 R_TimeReport("skystartframe");
9778
9779         if (cl.csqc_vidvars.drawworld)
9780         {
9781                 // don't let sound skip if going slow
9782                 if (r_refdef.scene.extraupdate)
9783                         S_ExtraUpdate ();
9784
9785                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9786                 {
9787                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9788                         if (r_timereport_active)
9789                                 R_TimeReport("worldsky");
9790                 }
9791
9792                 if (R_DrawBrushModelsSky() && r_timereport_active)
9793                         R_TimeReport("bmodelsky");
9794
9795                 if (skyrendermasked && skyrenderlater)
9796                 {
9797                         // we have to force off the water clipping plane while rendering sky
9798                         R_SetupView(false);
9799                         R_Sky();
9800                         R_SetupView(true);
9801                         if (r_timereport_active)
9802                                 R_TimeReport("sky");
9803                 }
9804         }
9805
9806         R_AnimCache_CacheVisibleEntities();
9807         if (r_timereport_active)
9808                 R_TimeReport("animation");
9809
9810         R_Shadow_PrepareLights();
9811         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9812                 R_Shadow_PrepareModelShadows();
9813         if (r_timereport_active)
9814                 R_TimeReport("preparelights");
9815
9816         if (R_Shadow_ShadowMappingEnabled())
9817                 shadowmapping = true;
9818
9819         if (r_shadow_usingdeferredprepass)
9820                 R_Shadow_DrawPrepass();
9821
9822         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9823         {
9824                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9825                 if (r_timereport_active)
9826                         R_TimeReport("worlddepth");
9827         }
9828         if (r_depthfirst.integer >= 2)
9829         {
9830                 R_DrawModelsDepth();
9831                 if (r_timereport_active)
9832                         R_TimeReport("modeldepth");
9833         }
9834
9835         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9836         {
9837                 R_DrawModelShadowMaps();
9838                 R_ResetViewRendering3D();
9839                 // don't let sound skip if going slow
9840                 if (r_refdef.scene.extraupdate)
9841                         S_ExtraUpdate ();
9842         }
9843
9844         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9845         {
9846                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9847                 if (r_timereport_active)
9848                         R_TimeReport("world");
9849         }
9850
9851         // don't let sound skip if going slow
9852         if (r_refdef.scene.extraupdate)
9853                 S_ExtraUpdate ();
9854
9855         R_DrawModels();
9856         if (r_timereport_active)
9857                 R_TimeReport("models");
9858
9859         // don't let sound skip if going slow
9860         if (r_refdef.scene.extraupdate)
9861                 S_ExtraUpdate ();
9862
9863         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9864         {
9865                 R_DrawModelShadows();
9866                 R_ResetViewRendering3D();
9867                 // don't let sound skip if going slow
9868                 if (r_refdef.scene.extraupdate)
9869                         S_ExtraUpdate ();
9870         }
9871
9872         if (!r_shadow_usingdeferredprepass)
9873         {
9874                 R_Shadow_DrawLights();
9875                 if (r_timereport_active)
9876                         R_TimeReport("rtlights");
9877         }
9878
9879         // don't let sound skip if going slow
9880         if (r_refdef.scene.extraupdate)
9881                 S_ExtraUpdate ();
9882
9883         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9884         {
9885                 R_DrawModelShadows();
9886                 R_ResetViewRendering3D();
9887                 // don't let sound skip if going slow
9888                 if (r_refdef.scene.extraupdate)
9889                         S_ExtraUpdate ();
9890         }
9891
9892         if (cl.csqc_vidvars.drawworld)
9893         {
9894                 if (cl_decals_newsystem.integer)
9895                 {
9896                         R_DrawModelDecals();
9897                         if (r_timereport_active)
9898                                 R_TimeReport("modeldecals");
9899                 }
9900                 else
9901                 {
9902                         R_DrawDecals();
9903                         if (r_timereport_active)
9904                                 R_TimeReport("decals");
9905                 }
9906
9907                 R_DrawParticles();
9908                 if (r_timereport_active)
9909                         R_TimeReport("particles");
9910
9911                 R_DrawExplosions();
9912                 if (r_timereport_active)
9913                         R_TimeReport("explosions");
9914
9915                 R_DrawLightningBeams();
9916                 if (r_timereport_active)
9917                         R_TimeReport("lightning");
9918         }
9919
9920         VM_CL_AddPolygonsToMeshQueue();
9921
9922         if (r_refdef.view.showdebug)
9923         {
9924                 if (cl_locs_show.integer)
9925                 {
9926                         R_DrawLocs();
9927                         if (r_timereport_active)
9928                                 R_TimeReport("showlocs");
9929                 }
9930
9931                 if (r_drawportals.integer)
9932                 {
9933                         R_DrawPortals();
9934                         if (r_timereport_active)
9935                                 R_TimeReport("portals");
9936                 }
9937
9938                 if (r_showbboxes.value > 0)
9939                 {
9940                         R_DrawEntityBBoxes();
9941                         if (r_timereport_active)
9942                                 R_TimeReport("bboxes");
9943                 }
9944         }
9945
9946         R_MeshQueue_RenderTransparent();
9947         if (r_timereport_active)
9948                 R_TimeReport("drawtrans");
9949
9950         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))
9951         {
9952                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9953                 if (r_timereport_active)
9954                         R_TimeReport("worlddebug");
9955                 R_DrawModelsDebug();
9956                 if (r_timereport_active)
9957                         R_TimeReport("modeldebug");
9958         }
9959
9960         if (cl.csqc_vidvars.drawworld)
9961         {
9962                 R_Shadow_DrawCoronas();
9963                 if (r_timereport_active)
9964                         R_TimeReport("coronas");
9965         }
9966
9967 #if 0
9968         {
9969                 GL_DepthTest(false);
9970                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9971                 GL_Color(1, 1, 1, 1);
9972                 qglBegin(GL_POLYGON);
9973                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9974                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9975                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9976                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9977                 qglEnd();
9978                 qglBegin(GL_POLYGON);
9979                 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]);
9980                 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]);
9981                 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]);
9982                 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]);
9983                 qglEnd();
9984                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9985         }
9986 #endif
9987
9988         // don't let sound skip if going slow
9989         if (r_refdef.scene.extraupdate)
9990                 S_ExtraUpdate ();
9991
9992         R_ResetViewRendering2D();
9993 }
9994
9995 static const unsigned short bboxelements[36] =
9996 {
9997         5, 1, 3, 5, 3, 7,
9998         6, 2, 0, 6, 0, 4,
9999         7, 3, 2, 7, 2, 6,
10000         4, 0, 1, 4, 1, 5,
10001         4, 5, 7, 4, 7, 6,
10002         1, 0, 2, 1, 2, 3,
10003 };
10004
10005 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
10006 {
10007         int i;
10008         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
10009
10010         RSurf_ActiveWorldEntity();
10011
10012         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10013         GL_DepthMask(false);
10014         GL_DepthRange(0, 1);
10015         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10016 //      R_Mesh_ResetTextureState();
10017
10018         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
10019         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
10020         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
10021         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
10022         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
10023         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
10024         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
10025         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
10026         R_FillColors(color4f, 8, cr, cg, cb, ca);
10027         if (r_refdef.fogenabled)
10028         {
10029                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
10030                 {
10031                         f1 = RSurf_FogVertex(v);
10032                         f2 = 1 - f1;
10033                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
10034                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
10035                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
10036                 }
10037         }
10038         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
10039         R_Mesh_ResetTextureState();
10040         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10041         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
10042 }
10043
10044 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10045 {
10046         int i;
10047         float color[4];
10048         prvm_edict_t *edict;
10049         prvm_prog_t *prog_save = prog;
10050
10051         // this function draws bounding boxes of server entities
10052         if (!sv.active)
10053                 return;
10054
10055         GL_CullFace(GL_NONE);
10056         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10057
10058         prog = 0;
10059         SV_VM_Begin();
10060         for (i = 0;i < numsurfaces;i++)
10061         {
10062                 edict = PRVM_EDICT_NUM(surfacelist[i]);
10063                 switch ((int)edict->fields.server->solid)
10064                 {
10065                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
10066                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
10067                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
10068                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
10069                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
10070                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
10071                 }
10072                 color[3] *= r_showbboxes.value;
10073                 color[3] = bound(0, color[3], 1);
10074                 GL_DepthTest(!r_showdisabledepthtest.integer);
10075                 GL_CullFace(r_refdef.view.cullface_front);
10076                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10077         }
10078         SV_VM_End();
10079         prog = prog_save;
10080 }
10081
10082 static void R_DrawEntityBBoxes(void)
10083 {
10084         int i;
10085         prvm_edict_t *edict;
10086         vec3_t center;
10087         prvm_prog_t *prog_save = prog;
10088
10089         // this function draws bounding boxes of server entities
10090         if (!sv.active)
10091                 return;
10092
10093         prog = 0;
10094         SV_VM_Begin();
10095         for (i = 0;i < prog->num_edicts;i++)
10096         {
10097                 edict = PRVM_EDICT_NUM(i);
10098                 if (edict->priv.server->free)
10099                         continue;
10100                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10101                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10102                         continue;
10103                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10104                         continue;
10105                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10106                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10107         }
10108         SV_VM_End();
10109         prog = prog_save;
10110 }
10111
10112 static const int nomodelelement3i[24] =
10113 {
10114         5, 2, 0,
10115         5, 1, 2,
10116         5, 0, 3,
10117         5, 3, 1,
10118         0, 2, 4,
10119         2, 1, 4,
10120         3, 0, 4,
10121         1, 3, 4
10122 };
10123
10124 static const unsigned short nomodelelement3s[24] =
10125 {
10126         5, 2, 0,
10127         5, 1, 2,
10128         5, 0, 3,
10129         5, 3, 1,
10130         0, 2, 4,
10131         2, 1, 4,
10132         3, 0, 4,
10133         1, 3, 4
10134 };
10135
10136 static const float nomodelvertex3f[6*3] =
10137 {
10138         -16,   0,   0,
10139          16,   0,   0,
10140           0, -16,   0,
10141           0,  16,   0,
10142           0,   0, -16,
10143           0,   0,  16
10144 };
10145
10146 static const float nomodelcolor4f[6*4] =
10147 {
10148         0.0f, 0.0f, 0.5f, 1.0f,
10149         0.0f, 0.0f, 0.5f, 1.0f,
10150         0.0f, 0.5f, 0.0f, 1.0f,
10151         0.0f, 0.5f, 0.0f, 1.0f,
10152         0.5f, 0.0f, 0.0f, 1.0f,
10153         0.5f, 0.0f, 0.0f, 1.0f
10154 };
10155
10156 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10157 {
10158         int i;
10159         float f1, f2, *c;
10160         float color4f[6*4];
10161
10162         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);
10163
10164         // this is only called once per entity so numsurfaces is always 1, and
10165         // surfacelist is always {0}, so this code does not handle batches
10166
10167         if (rsurface.ent_flags & RENDER_ADDITIVE)
10168         {
10169                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10170                 GL_DepthMask(false);
10171         }
10172         else if (rsurface.colormod[3] < 1)
10173         {
10174                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10175                 GL_DepthMask(false);
10176         }
10177         else
10178         {
10179                 GL_BlendFunc(GL_ONE, GL_ZERO);
10180                 GL_DepthMask(true);
10181         }
10182         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10183         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10184         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10185         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10186         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10187         for (i = 0, c = color4f;i < 6;i++, c += 4)
10188         {
10189                 c[0] *= rsurface.colormod[0];
10190                 c[1] *= rsurface.colormod[1];
10191                 c[2] *= rsurface.colormod[2];
10192                 c[3] *= rsurface.colormod[3];
10193         }
10194         if (r_refdef.fogenabled)
10195         {
10196                 for (i = 0, c = color4f;i < 6;i++, c += 4)
10197                 {
10198                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10199                         f2 = 1 - f1;
10200                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10201                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10202                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10203                 }
10204         }
10205 //      R_Mesh_ResetTextureState();
10206         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10207         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10208         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10209 }
10210
10211 void R_DrawNoModel(entity_render_t *ent)
10212 {
10213         vec3_t org;
10214         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10215         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10216                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10217         else
10218                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10219 }
10220
10221 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10222 {
10223         vec3_t right1, right2, diff, normal;
10224
10225         VectorSubtract (org2, org1, normal);
10226
10227         // calculate 'right' vector for start
10228         VectorSubtract (r_refdef.view.origin, org1, diff);
10229         CrossProduct (normal, diff, right1);
10230         VectorNormalize (right1);
10231
10232         // calculate 'right' vector for end
10233         VectorSubtract (r_refdef.view.origin, org2, diff);
10234         CrossProduct (normal, diff, right2);
10235         VectorNormalize (right2);
10236
10237         vert[ 0] = org1[0] + width * right1[0];
10238         vert[ 1] = org1[1] + width * right1[1];
10239         vert[ 2] = org1[2] + width * right1[2];
10240         vert[ 3] = org1[0] - width * right1[0];
10241         vert[ 4] = org1[1] - width * right1[1];
10242         vert[ 5] = org1[2] - width * right1[2];
10243         vert[ 6] = org2[0] - width * right2[0];
10244         vert[ 7] = org2[1] - width * right2[1];
10245         vert[ 8] = org2[2] - width * right2[2];
10246         vert[ 9] = org2[0] + width * right2[0];
10247         vert[10] = org2[1] + width * right2[1];
10248         vert[11] = org2[2] + width * right2[2];
10249 }
10250
10251 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)
10252 {
10253         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10254         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10255         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10256         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10257         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10258         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10259         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10260         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10261         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10262         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10263         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10264         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10265 }
10266
10267 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10268 {
10269         int i;
10270         float *vertex3f;
10271         float v[3];
10272         VectorSet(v, x, y, z);
10273         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10274                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10275                         break;
10276         if (i == mesh->numvertices)
10277         {
10278                 if (mesh->numvertices < mesh->maxvertices)
10279                 {
10280                         VectorCopy(v, vertex3f);
10281                         mesh->numvertices++;
10282                 }
10283                 return mesh->numvertices;
10284         }
10285         else
10286                 return i;
10287 }
10288
10289 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10290 {
10291         int i;
10292         int *e, element[3];
10293         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10294         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10295         e = mesh->element3i + mesh->numtriangles * 3;
10296         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10297         {
10298                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10299                 if (mesh->numtriangles < mesh->maxtriangles)
10300                 {
10301                         *e++ = element[0];
10302                         *e++ = element[1];
10303                         *e++ = element[2];
10304                         mesh->numtriangles++;
10305                 }
10306                 element[1] = element[2];
10307         }
10308 }
10309
10310 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10311 {
10312         int i;
10313         int *e, element[3];
10314         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10315         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10316         e = mesh->element3i + mesh->numtriangles * 3;
10317         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10318         {
10319                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10320                 if (mesh->numtriangles < mesh->maxtriangles)
10321                 {
10322                         *e++ = element[0];
10323                         *e++ = element[1];
10324                         *e++ = element[2];
10325                         mesh->numtriangles++;
10326                 }
10327                 element[1] = element[2];
10328         }
10329 }
10330
10331 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10332 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10333 {
10334         int planenum, planenum2;
10335         int w;
10336         int tempnumpoints;
10337         mplane_t *plane, *plane2;
10338         double maxdist;
10339         double temppoints[2][256*3];
10340         // figure out how large a bounding box we need to properly compute this brush
10341         maxdist = 0;
10342         for (w = 0;w < numplanes;w++)
10343                 maxdist = max(maxdist, fabs(planes[w].dist));
10344         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10345         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10346         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10347         {
10348                 w = 0;
10349                 tempnumpoints = 4;
10350                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10351                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10352                 {
10353                         if (planenum2 == planenum)
10354                                 continue;
10355                         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);
10356                         w = !w;
10357                 }
10358                 if (tempnumpoints < 3)
10359                         continue;
10360                 // generate elements forming a triangle fan for this polygon
10361                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10362         }
10363 }
10364
10365 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)
10366 {
10367         texturelayer_t *layer;
10368         layer = t->currentlayers + t->currentnumlayers++;
10369         layer->type = type;
10370         layer->depthmask = depthmask;
10371         layer->blendfunc1 = blendfunc1;
10372         layer->blendfunc2 = blendfunc2;
10373         layer->texture = texture;
10374         layer->texmatrix = *matrix;
10375         layer->color[0] = r;
10376         layer->color[1] = g;
10377         layer->color[2] = b;
10378         layer->color[3] = a;
10379 }
10380
10381 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10382 {
10383         if(parms[0] == 0 && parms[1] == 0)
10384                 return false;
10385         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10386                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10387                         return false;
10388         return true;
10389 }
10390
10391 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10392 {
10393         double index, f;
10394         index = parms[2] + r_refdef.scene.time * parms[3];
10395         index -= floor(index);
10396         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10397         {
10398         default:
10399         case Q3WAVEFUNC_NONE:
10400         case Q3WAVEFUNC_NOISE:
10401         case Q3WAVEFUNC_COUNT:
10402                 f = 0;
10403                 break;
10404         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10405         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10406         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10407         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10408         case Q3WAVEFUNC_TRIANGLE:
10409                 index *= 4;
10410                 f = index - floor(index);
10411                 if (index < 1)
10412                         f = f;
10413                 else if (index < 2)
10414                         f = 1 - f;
10415                 else if (index < 3)
10416                         f = -f;
10417                 else
10418                         f = -(1 - f);
10419                 break;
10420         }
10421         f = parms[0] + parms[1] * f;
10422         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10423                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10424         return (float) f;
10425 }
10426
10427 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10428 {
10429         int w, h, idx;
10430         float f;
10431         float tcmat[12];
10432         matrix4x4_t matrix, temp;
10433         switch(tcmod->tcmod)
10434         {
10435                 case Q3TCMOD_COUNT:
10436                 case Q3TCMOD_NONE:
10437                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10438                                 matrix = r_waterscrollmatrix;
10439                         else
10440                                 matrix = identitymatrix;
10441                         break;
10442                 case Q3TCMOD_ENTITYTRANSLATE:
10443                         // this is used in Q3 to allow the gamecode to control texcoord
10444                         // scrolling on the entity, which is not supported in darkplaces yet.
10445                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10446                         break;
10447                 case Q3TCMOD_ROTATE:
10448                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10449                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10450                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10451                         break;
10452                 case Q3TCMOD_SCALE:
10453                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10454                         break;
10455                 case Q3TCMOD_SCROLL:
10456                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10457                         break;
10458                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10459                         w = (int) tcmod->parms[0];
10460                         h = (int) tcmod->parms[1];
10461                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10462                         f = f - floor(f);
10463                         idx = (int) floor(f * w * h);
10464                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10465                         break;
10466                 case Q3TCMOD_STRETCH:
10467                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10468                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10469                         break;
10470                 case Q3TCMOD_TRANSFORM:
10471                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10472                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10473                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10474                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10475                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10476                         break;
10477                 case Q3TCMOD_TURBULENT:
10478                         // this is handled in the RSurf_PrepareVertices function
10479                         matrix = identitymatrix;
10480                         break;
10481         }
10482         temp = *texmatrix;
10483         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10484 }
10485
10486 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10487 {
10488         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10489         char name[MAX_QPATH];
10490         skinframe_t *skinframe;
10491         unsigned char pixels[296*194];
10492         strlcpy(cache->name, skinname, sizeof(cache->name));
10493         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10494         if (developer_loading.integer)
10495                 Con_Printf("loading %s\n", name);
10496         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10497         if (!skinframe || !skinframe->base)
10498         {
10499                 unsigned char *f;
10500                 fs_offset_t filesize;
10501                 skinframe = NULL;
10502                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10503                 if (f)
10504                 {
10505                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10506                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10507                         Mem_Free(f);
10508                 }
10509         }
10510         cache->skinframe = skinframe;
10511 }
10512
10513 texture_t *R_GetCurrentTexture(texture_t *t)
10514 {
10515         int i;
10516         const entity_render_t *ent = rsurface.entity;
10517         dp_model_t *model = ent->model;
10518         q3shaderinfo_layer_tcmod_t *tcmod;
10519
10520         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10521                 return t->currentframe;
10522         t->update_lastrenderframe = r_textureframe;
10523         t->update_lastrenderentity = (void *)ent;
10524
10525         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10526                 t->camera_entity = ent->entitynumber;
10527         else
10528                 t->camera_entity = 0;
10529
10530         // switch to an alternate material if this is a q1bsp animated material
10531         {
10532                 texture_t *texture = t;
10533                 int s = rsurface.ent_skinnum;
10534                 if ((unsigned int)s >= (unsigned int)model->numskins)
10535                         s = 0;
10536                 if (model->skinscenes)
10537                 {
10538                         if (model->skinscenes[s].framecount > 1)
10539                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10540                         else
10541                                 s = model->skinscenes[s].firstframe;
10542                 }
10543                 if (s > 0)
10544                         t = t + s * model->num_surfaces;
10545                 if (t->animated)
10546                 {
10547                         // use an alternate animation if the entity's frame is not 0,
10548                         // and only if the texture has an alternate animation
10549                         if (rsurface.ent_alttextures && t->anim_total[1])
10550                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10551                         else
10552                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10553                 }
10554                 texture->currentframe = t;
10555         }
10556
10557         // update currentskinframe to be a qw skin or animation frame
10558         if (rsurface.ent_qwskin >= 0)
10559         {
10560                 i = rsurface.ent_qwskin;
10561                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10562                 {
10563                         r_qwskincache_size = cl.maxclients;
10564                         if (r_qwskincache)
10565                                 Mem_Free(r_qwskincache);
10566                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10567                 }
10568                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10569                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10570                 t->currentskinframe = r_qwskincache[i].skinframe;
10571                 if (t->currentskinframe == NULL)
10572                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10573         }
10574         else if (t->numskinframes >= 2)
10575                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10576         if (t->backgroundnumskinframes >= 2)
10577                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10578
10579         t->currentmaterialflags = t->basematerialflags;
10580         t->currentalpha = rsurface.colormod[3];
10581         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10582                 t->currentalpha *= r_wateralpha.value;
10583         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10584                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10585         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10586                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10587         if (!(rsurface.ent_flags & RENDER_LIGHT))
10588                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10589         else if (FAKELIGHT_ENABLED)
10590         {
10591                         // no modellight if using fakelight for the map
10592         }
10593         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10594         {
10595                 // pick a model lighting mode
10596                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10597                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10598                 else
10599                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10600         }
10601         if (rsurface.ent_flags & RENDER_ADDITIVE)
10602                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10603         else if (t->currentalpha < 1)
10604                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10605         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10606                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10607         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10608                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10609         if (t->backgroundnumskinframes)
10610                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10611         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10612         {
10613                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10614                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10615         }
10616         else
10617                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10618         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10619                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10620
10621         // there is no tcmod
10622         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10623         {
10624                 t->currenttexmatrix = r_waterscrollmatrix;
10625                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10626         }
10627         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10628         {
10629                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10630                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10631         }
10632
10633         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10634                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10635         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10636                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10637
10638         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10639         if (t->currentskinframe->qpixels)
10640                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10641         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10642         if (!t->basetexture)
10643                 t->basetexture = r_texture_notexture;
10644         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10645         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10646         t->nmaptexture = t->currentskinframe->nmap;
10647         if (!t->nmaptexture)
10648                 t->nmaptexture = r_texture_blanknormalmap;
10649         t->glosstexture = r_texture_black;
10650         t->glowtexture = t->currentskinframe->glow;
10651         t->fogtexture = t->currentskinframe->fog;
10652         t->reflectmasktexture = t->currentskinframe->reflect;
10653         if (t->backgroundnumskinframes)
10654         {
10655                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10656                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10657                 t->backgroundglosstexture = r_texture_black;
10658                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10659                 if (!t->backgroundnmaptexture)
10660                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10661         }
10662         else
10663         {
10664                 t->backgroundbasetexture = r_texture_white;
10665                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10666                 t->backgroundglosstexture = r_texture_black;
10667                 t->backgroundglowtexture = NULL;
10668         }
10669         t->specularpower = r_shadow_glossexponent.value;
10670         // TODO: store reference values for these in the texture?
10671         t->specularscale = 0;
10672         if (r_shadow_gloss.integer > 0)
10673         {
10674                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10675                 {
10676                         if (r_shadow_glossintensity.value > 0)
10677                         {
10678                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10679                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10680                                 t->specularscale = r_shadow_glossintensity.value;
10681                         }
10682                 }
10683                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10684                 {
10685                         t->glosstexture = r_texture_white;
10686                         t->backgroundglosstexture = r_texture_white;
10687                         t->specularscale = r_shadow_gloss2intensity.value;
10688                         t->specularpower = r_shadow_gloss2exponent.value;
10689                 }
10690         }
10691         t->specularscale *= t->specularscalemod;
10692         t->specularpower *= t->specularpowermod;
10693
10694         // lightmaps mode looks bad with dlights using actual texturing, so turn
10695         // off the colormap and glossmap, but leave the normalmap on as it still
10696         // accurately represents the shading involved
10697         if (gl_lightmaps.integer)
10698         {
10699                 t->basetexture = r_texture_grey128;
10700                 t->pantstexture = r_texture_black;
10701                 t->shirttexture = r_texture_black;
10702                 t->nmaptexture = r_texture_blanknormalmap;
10703                 t->glosstexture = r_texture_black;
10704                 t->glowtexture = NULL;
10705                 t->fogtexture = NULL;
10706                 t->reflectmasktexture = NULL;
10707                 t->backgroundbasetexture = NULL;
10708                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10709                 t->backgroundglosstexture = r_texture_black;
10710                 t->backgroundglowtexture = NULL;
10711                 t->specularscale = 0;
10712                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10713         }
10714
10715         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10716         VectorClear(t->dlightcolor);
10717         t->currentnumlayers = 0;
10718         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10719         {
10720                 int blendfunc1, blendfunc2;
10721                 qboolean depthmask;
10722                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10723                 {
10724                         blendfunc1 = GL_SRC_ALPHA;
10725                         blendfunc2 = GL_ONE;
10726                 }
10727                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10728                 {
10729                         blendfunc1 = GL_SRC_ALPHA;
10730                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10731                 }
10732                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10733                 {
10734                         blendfunc1 = t->customblendfunc[0];
10735                         blendfunc2 = t->customblendfunc[1];
10736                 }
10737                 else
10738                 {
10739                         blendfunc1 = GL_ONE;
10740                         blendfunc2 = GL_ZERO;
10741                 }
10742                 // don't colormod evilblend textures
10743                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10744                         VectorSet(t->lightmapcolor, 1, 1, 1);
10745                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10746                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10747                 {
10748                         // fullbright is not affected by r_refdef.lightmapintensity
10749                         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]);
10750                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10751                                 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]);
10752                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10753                                 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]);
10754                 }
10755                 else
10756                 {
10757                         vec3_t ambientcolor;
10758                         float colorscale;
10759                         // set the color tint used for lights affecting this surface
10760                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10761                         colorscale = 2;
10762                         // q3bsp has no lightmap updates, so the lightstylevalue that
10763                         // would normally be baked into the lightmap must be
10764                         // applied to the color
10765                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10766                         if (model->type == mod_brushq3)
10767                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10768                         colorscale *= r_refdef.lightmapintensity;
10769                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10770                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10771                         // basic lit geometry
10772                         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]);
10773                         // add pants/shirt if needed
10774                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10775                                 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]);
10776                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10777                                 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]);
10778                         // now add ambient passes if needed
10779                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10780                         {
10781                                 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]);
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] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[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] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
10786                         }
10787                 }
10788                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10789                         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]);
10790                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10791                 {
10792                         // if this is opaque use alpha blend which will darken the earlier
10793                         // passes cheaply.
10794                         //
10795                         // if this is an alpha blended material, all the earlier passes
10796                         // were darkened by fog already, so we only need to add the fog
10797                         // color ontop through the fog mask texture
10798                         //
10799                         // if this is an additive blended material, all the earlier passes
10800                         // were darkened by fog already, and we should not add fog color
10801                         // (because the background was not darkened, there is no fog color
10802                         // that was lost behind it).
10803                         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]);
10804                 }
10805         }
10806
10807         return t->currentframe;
10808 }
10809
10810 rsurfacestate_t rsurface;
10811
10812 void R_Mesh_ResizeArrays(int newvertices)
10813 {
10814         unsigned char *base;
10815         size_t size;
10816         if (rsurface.array_size >= newvertices)
10817                 return;
10818         if (rsurface.array_base)
10819                 Mem_Free(rsurface.array_base);
10820         rsurface.array_size = (newvertices + 1023) & ~1023;
10821         size = 0;
10822         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10823         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10824         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10825         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10826         size += rsurface.array_size * sizeof(float[3]);
10827         size += rsurface.array_size * sizeof(float[3]);
10828         size += rsurface.array_size * sizeof(float[3]);
10829         size += rsurface.array_size * sizeof(float[3]);
10830         size += rsurface.array_size * sizeof(float[3]);
10831         size += rsurface.array_size * sizeof(float[3]);
10832         size += rsurface.array_size * sizeof(float[3]);
10833         size += rsurface.array_size * sizeof(float[3]);
10834         size += rsurface.array_size * sizeof(float[4]);
10835         size += rsurface.array_size * sizeof(float[2]);
10836         size += rsurface.array_size * sizeof(float[2]);
10837         size += rsurface.array_size * sizeof(float[4]);
10838         size += rsurface.array_size * sizeof(int[3]);
10839         size += rsurface.array_size * sizeof(unsigned short[3]);
10840         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10841         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10842         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10843         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10844         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10845         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10846         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10847         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10848         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10849         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10850         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10851         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10852         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10853         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10854         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10855         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10856         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10857         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
10858         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10859 }
10860
10861 void RSurf_ActiveWorldEntity(void)
10862 {
10863         dp_model_t *model = r_refdef.scene.worldmodel;
10864         //if (rsurface.entity == r_refdef.scene.worldentity)
10865         //      return;
10866         rsurface.entity = r_refdef.scene.worldentity;
10867         rsurface.skeleton = NULL;
10868         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10869         rsurface.ent_skinnum = 0;
10870         rsurface.ent_qwskin = -1;
10871         rsurface.ent_shadertime = 0;
10872         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10873         R_Mesh_ResizeArrays(max(model->surfmesh.num_vertices, model->surfmesh.num_triangles));
10874         rsurface.matrix = identitymatrix;
10875         rsurface.inversematrix = identitymatrix;
10876         rsurface.matrixscale = 1;
10877         rsurface.inversematrixscale = 1;
10878         R_EntityMatrix(&identitymatrix);
10879         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10880         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10881         rsurface.fograngerecip = r_refdef.fograngerecip;
10882         rsurface.fogheightfade = r_refdef.fogheightfade;
10883         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10884         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10885         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10886         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10887         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10888         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10889         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10890         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10891         rsurface.colormod[3] = 1;
10892         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);
10893         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10894         rsurface.frameblend[0].lerp = 1;
10895         rsurface.ent_alttextures = false;
10896         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10897         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10898         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10899         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10900         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10901         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10902         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10903         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10904         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10905         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10906         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10907         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10908         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10909         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10910         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10911         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10912         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10913         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10914         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10915         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10916         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10917         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10918         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10919         rsurface.modelelement3i = model->surfmesh.data_element3i;
10920         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10921         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10922         rsurface.modelelement3s = model->surfmesh.data_element3s;
10923         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10924         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10925         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10926         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10927         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10928         rsurface.modelsurfaces = model->data_surfaces;
10929         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10930         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10931         rsurface.modelvertexposition = model->surfmesh.vertexposition;
10932         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10933         rsurface.modelgeneratedvertex = false;
10934         rsurface.batchgeneratedvertex = false;
10935         rsurface.batchfirstvertex = 0;
10936         rsurface.batchnumvertices = 0;
10937         rsurface.batchfirsttriangle = 0;
10938         rsurface.batchnumtriangles = 0;
10939         rsurface.batchvertex3f  = NULL;
10940         rsurface.batchvertex3f_vertexbuffer = NULL;
10941         rsurface.batchvertex3f_bufferoffset = 0;
10942         rsurface.batchsvector3f = NULL;
10943         rsurface.batchsvector3f_vertexbuffer = NULL;
10944         rsurface.batchsvector3f_bufferoffset = 0;
10945         rsurface.batchtvector3f = NULL;
10946         rsurface.batchtvector3f_vertexbuffer = NULL;
10947         rsurface.batchtvector3f_bufferoffset = 0;
10948         rsurface.batchnormal3f  = NULL;
10949         rsurface.batchnormal3f_vertexbuffer = NULL;
10950         rsurface.batchnormal3f_bufferoffset = 0;
10951         rsurface.batchlightmapcolor4f = NULL;
10952         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10953         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10954         rsurface.batchtexcoordtexture2f = NULL;
10955         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10956         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10957         rsurface.batchtexcoordlightmap2f = NULL;
10958         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10959         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10960         rsurface.batchvertexmesh = NULL;
10961         rsurface.batchvertexmeshbuffer = NULL;
10962         rsurface.batchvertexposition = NULL;
10963         rsurface.batchvertexpositionbuffer = NULL;
10964         rsurface.batchelement3i = NULL;
10965         rsurface.batchelement3i_indexbuffer = NULL;
10966         rsurface.batchelement3i_bufferoffset = 0;
10967         rsurface.batchelement3s = NULL;
10968         rsurface.batchelement3s_indexbuffer = NULL;
10969         rsurface.batchelement3s_bufferoffset = 0;
10970         rsurface.passcolor4f = NULL;
10971         rsurface.passcolor4f_vertexbuffer = NULL;
10972         rsurface.passcolor4f_bufferoffset = 0;
10973 }
10974
10975 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10976 {
10977         dp_model_t *model = ent->model;
10978         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10979         //      return;
10980         rsurface.entity = (entity_render_t *)ent;
10981         rsurface.skeleton = ent->skeleton;
10982         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10983         rsurface.ent_skinnum = ent->skinnum;
10984         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;
10985         rsurface.ent_shadertime = ent->shadertime;
10986         rsurface.ent_flags = ent->flags;
10987         R_Mesh_ResizeArrays(max(model->surfmesh.num_vertices, model->surfmesh.num_triangles));
10988         rsurface.matrix = ent->matrix;
10989         rsurface.inversematrix = ent->inversematrix;
10990         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10991         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10992         R_EntityMatrix(&rsurface.matrix);
10993         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10994         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10995         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10996         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10997         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10998         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10999         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
11000         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
11001         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
11002         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
11003         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
11004         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
11005         rsurface.colormod[3] = ent->alpha;
11006         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
11007         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
11008         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
11009         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11010         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11011         if (ent->model->brush.submodel && !prepass)
11012         {
11013                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
11014                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
11015         }
11016         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
11017         {
11018                 if (ent->animcache_vertex3f && !r_framedata_failed)
11019                 {
11020                         rsurface.modelvertex3f = ent->animcache_vertex3f;
11021                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
11022                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
11023                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
11024                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
11025                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
11026                         rsurface.modelvertexposition = ent->animcache_vertexposition;
11027                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
11028                 }
11029                 else if (wanttangents)
11030                 {
11031                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11032                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11033                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11034                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11035                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
11036                         rsurface.modelvertexmesh = NULL;
11037                         rsurface.modelvertexmeshbuffer = NULL;
11038                         rsurface.modelvertexposition = NULL;
11039                         rsurface.modelvertexpositionbuffer = NULL;
11040                 }
11041                 else if (wantnormals)
11042                 {
11043                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11044                         rsurface.modelsvector3f = NULL;
11045                         rsurface.modeltvector3f = NULL;
11046                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11047                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
11048                         rsurface.modelvertexmesh = NULL;
11049                         rsurface.modelvertexmeshbuffer = NULL;
11050                         rsurface.modelvertexposition = NULL;
11051                         rsurface.modelvertexpositionbuffer = NULL;
11052                 }
11053                 else
11054                 {
11055                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11056                         rsurface.modelsvector3f = NULL;
11057                         rsurface.modeltvector3f = NULL;
11058                         rsurface.modelnormal3f = NULL;
11059                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
11060                         rsurface.modelvertexmesh = NULL;
11061                         rsurface.modelvertexmeshbuffer = NULL;
11062                         rsurface.modelvertexposition = NULL;
11063                         rsurface.modelvertexpositionbuffer = NULL;
11064                 }
11065                 rsurface.modelvertex3f_vertexbuffer = 0;
11066                 rsurface.modelvertex3f_bufferoffset = 0;
11067                 rsurface.modelsvector3f_vertexbuffer = 0;
11068                 rsurface.modelsvector3f_bufferoffset = 0;
11069                 rsurface.modeltvector3f_vertexbuffer = 0;
11070                 rsurface.modeltvector3f_bufferoffset = 0;
11071                 rsurface.modelnormal3f_vertexbuffer = 0;
11072                 rsurface.modelnormal3f_bufferoffset = 0;
11073                 rsurface.modelgeneratedvertex = true;
11074         }
11075         else
11076         {
11077                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
11078                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11079                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11080                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11081                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11082                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11083                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11084                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11085                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11086                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
11087                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11088                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11089                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11090                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11091                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
11092                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
11093                 rsurface.modelgeneratedvertex = false;
11094         }
11095         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11096         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11097         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11098         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11099         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11100         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11101         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11102         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11103         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11104         rsurface.modelelement3i = model->surfmesh.data_element3i;
11105         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11106         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11107         rsurface.modelelement3s = model->surfmesh.data_element3s;
11108         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11109         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11110         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11111         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11112         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11113         rsurface.modelsurfaces = model->data_surfaces;
11114         rsurface.batchgeneratedvertex = false;
11115         rsurface.batchfirstvertex = 0;
11116         rsurface.batchnumvertices = 0;
11117         rsurface.batchfirsttriangle = 0;
11118         rsurface.batchnumtriangles = 0;
11119         rsurface.batchvertex3f  = NULL;
11120         rsurface.batchvertex3f_vertexbuffer = NULL;
11121         rsurface.batchvertex3f_bufferoffset = 0;
11122         rsurface.batchsvector3f = NULL;
11123         rsurface.batchsvector3f_vertexbuffer = NULL;
11124         rsurface.batchsvector3f_bufferoffset = 0;
11125         rsurface.batchtvector3f = NULL;
11126         rsurface.batchtvector3f_vertexbuffer = NULL;
11127         rsurface.batchtvector3f_bufferoffset = 0;
11128         rsurface.batchnormal3f  = NULL;
11129         rsurface.batchnormal3f_vertexbuffer = NULL;
11130         rsurface.batchnormal3f_bufferoffset = 0;
11131         rsurface.batchlightmapcolor4f = NULL;
11132         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11133         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11134         rsurface.batchtexcoordtexture2f = NULL;
11135         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11136         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11137         rsurface.batchtexcoordlightmap2f = NULL;
11138         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11139         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11140         rsurface.batchvertexmesh = NULL;
11141         rsurface.batchvertexmeshbuffer = NULL;
11142         rsurface.batchvertexposition = NULL;
11143         rsurface.batchvertexpositionbuffer = NULL;
11144         rsurface.batchelement3i = NULL;
11145         rsurface.batchelement3i_indexbuffer = NULL;
11146         rsurface.batchelement3i_bufferoffset = 0;
11147         rsurface.batchelement3s = NULL;
11148         rsurface.batchelement3s_indexbuffer = NULL;
11149         rsurface.batchelement3s_bufferoffset = 0;
11150         rsurface.passcolor4f = NULL;
11151         rsurface.passcolor4f_vertexbuffer = NULL;
11152         rsurface.passcolor4f_bufferoffset = 0;
11153 }
11154
11155 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)
11156 {
11157         int i;
11158
11159         rsurface.entity = r_refdef.scene.worldentity;
11160         rsurface.skeleton = NULL;
11161         rsurface.ent_skinnum = 0;
11162         rsurface.ent_qwskin = -1;
11163         rsurface.ent_shadertime = shadertime;
11164         rsurface.ent_flags = entflags;
11165         rsurface.modelnumvertices = numvertices;
11166         rsurface.modelnumtriangles = numtriangles;
11167         R_Mesh_ResizeArrays(max(rsurface.modelnumvertices, rsurface.modelnumtriangles));
11168         rsurface.matrix = *matrix;
11169         rsurface.inversematrix = *inversematrix;
11170         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11171         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11172         R_EntityMatrix(&rsurface.matrix);
11173         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11174         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11175         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11176         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11177         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11178         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11179         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11180         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11181         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11182         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11183         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11184         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11185         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);
11186         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11187         rsurface.frameblend[0].lerp = 1;
11188         rsurface.ent_alttextures = false;
11189         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11190         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11191         if (wanttangents)
11192         {
11193                 rsurface.modelvertex3f = vertex3f;
11194                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
11195                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
11196                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11197         }
11198         else if (wantnormals)
11199         {
11200                 rsurface.modelvertex3f = vertex3f;
11201                 rsurface.modelsvector3f = NULL;
11202                 rsurface.modeltvector3f = NULL;
11203                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11204         }
11205         else
11206         {
11207                 rsurface.modelvertex3f = vertex3f;
11208                 rsurface.modelsvector3f = NULL;
11209                 rsurface.modeltvector3f = NULL;
11210                 rsurface.modelnormal3f = NULL;
11211         }
11212         rsurface.modelvertexmesh = NULL;
11213         rsurface.modelvertexmeshbuffer = NULL;
11214         rsurface.modelvertexposition = NULL;
11215         rsurface.modelvertexpositionbuffer = NULL;
11216         rsurface.modelvertex3f_vertexbuffer = 0;
11217         rsurface.modelvertex3f_bufferoffset = 0;
11218         rsurface.modelsvector3f_vertexbuffer = 0;
11219         rsurface.modelsvector3f_bufferoffset = 0;
11220         rsurface.modeltvector3f_vertexbuffer = 0;
11221         rsurface.modeltvector3f_bufferoffset = 0;
11222         rsurface.modelnormal3f_vertexbuffer = 0;
11223         rsurface.modelnormal3f_bufferoffset = 0;
11224         rsurface.modelgeneratedvertex = true;
11225         rsurface.modellightmapcolor4f  = color4f;
11226         rsurface.modellightmapcolor4f_vertexbuffer = 0;
11227         rsurface.modellightmapcolor4f_bufferoffset = 0;
11228         rsurface.modeltexcoordtexture2f  = texcoord2f;
11229         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11230         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11231         rsurface.modeltexcoordlightmap2f  = NULL;
11232         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11233         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11234         rsurface.modelelement3i = element3i;
11235         rsurface.modelelement3i_indexbuffer = NULL;
11236         rsurface.modelelement3i_bufferoffset = 0;
11237         rsurface.modelelement3s = element3s;
11238         rsurface.modelelement3s_indexbuffer = NULL;
11239         rsurface.modelelement3s_bufferoffset = 0;
11240         rsurface.modellightmapoffsets = NULL;
11241         rsurface.modelsurfaces = NULL;
11242         rsurface.batchgeneratedvertex = false;
11243         rsurface.batchfirstvertex = 0;
11244         rsurface.batchnumvertices = 0;
11245         rsurface.batchfirsttriangle = 0;
11246         rsurface.batchnumtriangles = 0;
11247         rsurface.batchvertex3f  = NULL;
11248         rsurface.batchvertex3f_vertexbuffer = NULL;
11249         rsurface.batchvertex3f_bufferoffset = 0;
11250         rsurface.batchsvector3f = NULL;
11251         rsurface.batchsvector3f_vertexbuffer = NULL;
11252         rsurface.batchsvector3f_bufferoffset = 0;
11253         rsurface.batchtvector3f = NULL;
11254         rsurface.batchtvector3f_vertexbuffer = NULL;
11255         rsurface.batchtvector3f_bufferoffset = 0;
11256         rsurface.batchnormal3f  = NULL;
11257         rsurface.batchnormal3f_vertexbuffer = NULL;
11258         rsurface.batchnormal3f_bufferoffset = 0;
11259         rsurface.batchlightmapcolor4f = NULL;
11260         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11261         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11262         rsurface.batchtexcoordtexture2f = NULL;
11263         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11264         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11265         rsurface.batchtexcoordlightmap2f = NULL;
11266         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11267         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11268         rsurface.batchvertexmesh = NULL;
11269         rsurface.batchvertexmeshbuffer = NULL;
11270         rsurface.batchvertexposition = NULL;
11271         rsurface.batchvertexpositionbuffer = NULL;
11272         rsurface.batchelement3i = NULL;
11273         rsurface.batchelement3i_indexbuffer = NULL;
11274         rsurface.batchelement3i_bufferoffset = 0;
11275         rsurface.batchelement3s = NULL;
11276         rsurface.batchelement3s_indexbuffer = NULL;
11277         rsurface.batchelement3s_bufferoffset = 0;
11278         rsurface.passcolor4f = NULL;
11279         rsurface.passcolor4f_vertexbuffer = NULL;
11280         rsurface.passcolor4f_bufferoffset = 0;
11281
11282         if (rsurface.modelnumvertices && rsurface.modelelement3i)
11283         {
11284                 if ((wantnormals || wanttangents) && !normal3f)
11285                 {
11286                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11287                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11288                 }
11289                 if (wanttangents && !svector3f)
11290                 {
11291                         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);
11292                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11293                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11294                 }
11295         }
11296
11297         // now convert arrays into vertexmesh structs
11298         for (i = 0;i < numvertices;i++)
11299         {
11300                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
11301                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
11302                 if (rsurface.modelsvector3f)
11303                         VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
11304                 if (rsurface.modeltvector3f)
11305                         VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
11306                 if (rsurface.modelnormal3f)
11307                         VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
11308                 if (rsurface.modellightmapcolor4f)
11309                         Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
11310                 if (rsurface.modeltexcoordtexture2f)
11311                         Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
11312                 if (rsurface.modeltexcoordlightmap2f)
11313                         Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
11314         }
11315 }
11316
11317 float RSurf_FogPoint(const float *v)
11318 {
11319         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11320         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11321         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11322         float FogHeightFade = r_refdef.fogheightfade;
11323         float fogfrac;
11324         unsigned int fogmasktableindex;
11325         if (r_refdef.fogplaneviewabove)
11326                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11327         else
11328                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11329         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11330         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11331 }
11332
11333 float RSurf_FogVertex(const float *v)
11334 {
11335         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11336         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11337         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11338         float FogHeightFade = rsurface.fogheightfade;
11339         float fogfrac;
11340         unsigned int fogmasktableindex;
11341         if (r_refdef.fogplaneviewabove)
11342                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11343         else
11344                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11345         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11346         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11347 }
11348
11349 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11350 {
11351         int i;
11352         for (i = 0;i < numelements;i++)
11353                 outelement3i[i] = inelement3i[i] + adjust;
11354 }
11355
11356 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11357 extern cvar_t gl_vbo;
11358 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11359 {
11360         int deformindex;
11361         int firsttriangle;
11362         int numtriangles;
11363         int firstvertex;
11364         int endvertex;
11365         int numvertices;
11366         int surfacefirsttriangle;
11367         int surfacenumtriangles;
11368         int surfacefirstvertex;
11369         int surfaceendvertex;
11370         int surfacenumvertices;
11371         int needsupdate;
11372         int i, j;
11373         qboolean gaps;
11374         qboolean dynamicvertex;
11375         float amplitude;
11376         float animpos;
11377         float scale;
11378         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11379         float waveparms[4];
11380         q3shaderinfo_deform_t *deform;
11381         const msurface_t *surface, *firstsurface;
11382         r_vertexposition_t *vertexposition;
11383         r_vertexmesh_t *vertexmesh;
11384         if (!texturenumsurfaces)
11385                 return;
11386         // find vertex range of this surface batch
11387         gaps = false;
11388         firstsurface = texturesurfacelist[0];
11389         firsttriangle = firstsurface->num_firsttriangle;
11390         numtriangles = 0;
11391         firstvertex = endvertex = firstsurface->num_firstvertex;
11392         for (i = 0;i < texturenumsurfaces;i++)
11393         {
11394                 surface = texturesurfacelist[i];
11395                 if (surface != firstsurface + i)
11396                         gaps = true;
11397                 surfacefirstvertex = surface->num_firstvertex;
11398                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11399                 surfacenumtriangles = surface->num_triangles;
11400                 if (firstvertex > surfacefirstvertex)
11401                         firstvertex = surfacefirstvertex;
11402                 if (endvertex < surfaceendvertex)
11403                         endvertex = surfaceendvertex;
11404                 numtriangles += surfacenumtriangles;
11405         }
11406
11407         // we now know the vertex range used, and if there are any gaps in it
11408         rsurface.batchfirstvertex = firstvertex;
11409         rsurface.batchnumvertices = endvertex - firstvertex;
11410         rsurface.batchfirsttriangle = firsttriangle;
11411         rsurface.batchnumtriangles = numtriangles;
11412
11413         // this variable holds flags for which properties have been updated that
11414         // may require regenerating vertexmesh or vertexposition arrays...
11415         needsupdate = 0;
11416
11417         // check if any dynamic vertex processing must occur
11418         dynamicvertex = false;
11419
11420         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11421                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11422         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11423         {
11424                 switch (deform->deform)
11425                 {
11426                 default:
11427                 case Q3DEFORM_PROJECTIONSHADOW:
11428                 case Q3DEFORM_TEXT0:
11429                 case Q3DEFORM_TEXT1:
11430                 case Q3DEFORM_TEXT2:
11431                 case Q3DEFORM_TEXT3:
11432                 case Q3DEFORM_TEXT4:
11433                 case Q3DEFORM_TEXT5:
11434                 case Q3DEFORM_TEXT6:
11435                 case Q3DEFORM_TEXT7:
11436                 case Q3DEFORM_NONE:
11437                         break;
11438                 case Q3DEFORM_AUTOSPRITE:
11439                         dynamicvertex = true;
11440                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11441                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11442                         break;
11443                 case Q3DEFORM_AUTOSPRITE2:
11444                         dynamicvertex = true;
11445                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11446                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11447                         break;
11448                 case Q3DEFORM_NORMAL:
11449                         dynamicvertex = true;
11450                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11451                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11452                         break;
11453                 case Q3DEFORM_WAVE:
11454                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11455                                 break; // if wavefunc is a nop, ignore this transform
11456                         dynamicvertex = true;
11457                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11458                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11459                         break;
11460                 case Q3DEFORM_BULGE:
11461                         dynamicvertex = true;
11462                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11463                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11464                         break;
11465                 case Q3DEFORM_MOVE:
11466                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11467                                 break; // if wavefunc is a nop, ignore this transform
11468                         dynamicvertex = true;
11469                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11470                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11471                         break;
11472                 }
11473         }
11474         switch(rsurface.texture->tcgen.tcgen)
11475         {
11476         default:
11477         case Q3TCGEN_TEXTURE:
11478                 break;
11479         case Q3TCGEN_LIGHTMAP:
11480                 dynamicvertex = true;
11481                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11482                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11483                 break;
11484         case Q3TCGEN_VECTOR:
11485                 dynamicvertex = true;
11486                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11487                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11488                 break;
11489         case Q3TCGEN_ENVIRONMENT:
11490                 dynamicvertex = true;
11491                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11492                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11493                 break;
11494         }
11495         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11496         {
11497                 dynamicvertex = true;
11498                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11499                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11500         }
11501
11502         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11503         {
11504                 dynamicvertex = true;
11505                 batchneed |= BATCHNEED_NOGAPS;
11506                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11507         }
11508
11509         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11510         {
11511                 dynamicvertex = true;
11512                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11513                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11514         }
11515
11516         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11517         {
11518                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11519                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11520                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11521                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11522                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11523                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11524                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11525         }
11526
11527         // when the model data has no vertex buffer (dynamic mesh), we need to
11528         // eliminate gaps
11529         if (!rsurface.modelvertexmeshbuffer)
11530                 batchneed |= BATCHNEED_NOGAPS;
11531
11532         // if needsupdate, we have to do a dynamic vertex batch for sure
11533         if (needsupdate & batchneed)
11534                 dynamicvertex = true;
11535
11536         // see if we need to build vertexmesh from arrays
11537         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11538                 dynamicvertex = true;
11539
11540         // see if we need to build vertexposition from arrays
11541         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11542                 dynamicvertex = true;
11543
11544         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11545         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11546                 dynamicvertex = true;
11547
11548         // if there is a chance of animated vertex colors, it's a dynamic batch
11549         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11550                 dynamicvertex = true;
11551
11552         rsurface.batchvertex3f = rsurface.modelvertex3f;
11553         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11554         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11555         rsurface.batchsvector3f = rsurface.modelsvector3f;
11556         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11557         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11558         rsurface.batchtvector3f = rsurface.modeltvector3f;
11559         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11560         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11561         rsurface.batchnormal3f = rsurface.modelnormal3f;
11562         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11563         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11564         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11565         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11566         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11567         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11568         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11569         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11570         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11571         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11572         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11573         rsurface.batchvertexposition = rsurface.modelvertexposition;
11574         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11575         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11576         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11577         rsurface.batchelement3i = rsurface.modelelement3i;
11578         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11579         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11580         rsurface.batchelement3s = rsurface.modelelement3s;
11581         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11582         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11583
11584         // if any dynamic vertex processing has to occur in software, we copy the
11585         // entire surface list together before processing to rebase the vertices
11586         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11587         //
11588         // if any gaps exist and we do not have a static vertex buffer, we have to
11589         // copy the surface list together to avoid wasting upload bandwidth on the
11590         // vertices in the gaps.
11591         //
11592         // if gaps exist and we have a static vertex buffer, we still have to
11593         // combine the index buffer ranges into one dynamic index buffer.
11594         //
11595         // in all cases we end up with data that can be drawn in one call.
11596
11597         if (!dynamicvertex)
11598         {
11599                 // static vertex data, just set pointers...
11600                 rsurface.batchgeneratedvertex = false;
11601                 // if there are gaps, we want to build a combined index buffer,
11602                 // otherwise use the original static buffer with an appropriate offset
11603                 if (gaps)
11604                 {
11605                         firsttriangle = 0;
11606                         numtriangles = 0;
11607                         for (i = 0;i < texturenumsurfaces;i++)
11608                         {
11609                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11610                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11611                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11612                                 numtriangles += surfacenumtriangles;
11613                         }
11614                         rsurface.batchelement3i = rsurface.array_batchelement3i;
11615                         rsurface.batchelement3i_indexbuffer = NULL;
11616                         rsurface.batchelement3i_bufferoffset = 0;
11617                         rsurface.batchelement3s = NULL;
11618                         rsurface.batchelement3s_indexbuffer = NULL;
11619                         rsurface.batchelement3s_bufferoffset = 0;
11620                         if (endvertex <= 65536)
11621                         {
11622                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
11623                                 for (i = 0;i < numtriangles*3;i++)
11624                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11625                         }
11626                         rsurface.batchfirsttriangle = firsttriangle;
11627                         rsurface.batchnumtriangles = numtriangles;
11628                 }
11629                 return;
11630         }
11631
11632         // something needs software processing, do it for real...
11633         // we only directly handle interleaved array data in this case...
11634         rsurface.batchgeneratedvertex = true;
11635
11636         // now copy the vertex data into a combined array and make an index array
11637         // (this is what Quake3 does all the time)
11638         //if (gaps || rsurface.batchfirstvertex)
11639         {
11640                 rsurface.batchvertexposition = NULL;
11641                 rsurface.batchvertexpositionbuffer = NULL;
11642                 rsurface.batchvertexmesh = NULL;
11643                 rsurface.batchvertexmeshbuffer = NULL;
11644                 rsurface.batchvertex3f = NULL;
11645                 rsurface.batchvertex3f_vertexbuffer = NULL;
11646                 rsurface.batchvertex3f_bufferoffset = 0;
11647                 rsurface.batchsvector3f = NULL;
11648                 rsurface.batchsvector3f_vertexbuffer = NULL;
11649                 rsurface.batchsvector3f_bufferoffset = 0;
11650                 rsurface.batchtvector3f = NULL;
11651                 rsurface.batchtvector3f_vertexbuffer = NULL;
11652                 rsurface.batchtvector3f_bufferoffset = 0;
11653                 rsurface.batchnormal3f = NULL;
11654                 rsurface.batchnormal3f_vertexbuffer = NULL;
11655                 rsurface.batchnormal3f_bufferoffset = 0;
11656                 rsurface.batchlightmapcolor4f = NULL;
11657                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11658                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11659                 rsurface.batchtexcoordtexture2f = NULL;
11660                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11661                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11662                 rsurface.batchtexcoordlightmap2f = NULL;
11663                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11664                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11665                 rsurface.batchelement3i = rsurface.array_batchelement3i;
11666                 rsurface.batchelement3i_indexbuffer = NULL;
11667                 rsurface.batchelement3i_bufferoffset = 0;
11668                 rsurface.batchelement3s = NULL;
11669                 rsurface.batchelement3s_indexbuffer = NULL;
11670                 rsurface.batchelement3s_bufferoffset = 0;
11671                 // we'll only be setting up certain arrays as needed
11672                 if (batchneed & BATCHNEED_VERTEXPOSITION)
11673                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11674                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11675                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11676                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11677                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11678                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11679                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11680                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11681                 {
11682                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11683                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11684                 }
11685                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11686                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11687                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11688                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11689                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11690                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11691                 numvertices = 0;
11692                 numtriangles = 0;
11693                 for (i = 0;i < texturenumsurfaces;i++)
11694                 {
11695                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11696                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11697                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11698                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11699                         // copy only the data requested
11700                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11701                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11702                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11703                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11704                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11705                         {
11706                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11707                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11708                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11709                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11710                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11711                                 {
11712                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11713                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11714                                 }
11715                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11716                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11717                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11718                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11719                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11720                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11721                         }
11722                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11723                         numvertices += surfacenumvertices;
11724                         numtriangles += surfacenumtriangles;
11725                 }
11726
11727                 // generate a 16bit index array as well if possible
11728                 // (in general, dynamic batches fit)
11729                 if (numvertices <= 65536)
11730                 {
11731                         rsurface.batchelement3s = rsurface.array_batchelement3s;
11732                         for (i = 0;i < numtriangles*3;i++)
11733                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11734                 }
11735
11736                 // since we've copied everything, the batch now starts at 0
11737                 rsurface.batchfirstvertex = 0;
11738                 rsurface.batchnumvertices = numvertices;
11739                 rsurface.batchfirsttriangle = 0;
11740                 rsurface.batchnumtriangles = numtriangles;
11741         }
11742
11743         // q1bsp surfaces rendered in vertex color mode have to have colors
11744         // calculated based on lightstyles
11745         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11746         {
11747                 // generate color arrays for the surfaces in this list
11748                 int c[4];
11749                 int scale;
11750                 int size3;
11751                 const int *offsets;
11752                 const unsigned char *lm;
11753                 numvertices = 0;
11754                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11755                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11756                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11757                 for (i = 0;i < texturenumsurfaces;i++)
11758                 {
11759                         surface = texturesurfacelist[i];
11760                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11761                         surfacenumvertices = surface->num_vertices;
11762                         if (surface->lightmapinfo->samples)
11763                         {
11764                                 for (j = 0;j < surfacenumvertices;j++)
11765                                 {
11766                                         lm = surface->lightmapinfo->samples + offsets[j];
11767                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11768                                         VectorScale(lm, scale, c);
11769                                         if (surface->lightmapinfo->styles[1] != 255)
11770                                         {
11771                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11772                                                 lm += size3;
11773                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11774                                                 VectorMA(c, scale, lm, c);
11775                                                 if (surface->lightmapinfo->styles[2] != 255)
11776                                                 {
11777                                                         lm += size3;
11778                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11779                                                         VectorMA(c, scale, lm, c);
11780                                                         if (surface->lightmapinfo->styles[3] != 255)
11781                                                         {
11782                                                                 lm += size3;
11783                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11784                                                                 VectorMA(c, scale, lm, c);
11785                                                         }
11786                                                 }
11787                                         }
11788                                         c[0] >>= 15;
11789                                         c[1] >>= 15;
11790                                         c[2] >>= 15;
11791                                         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);
11792                                         numvertices++;
11793                                 }
11794                         }
11795                         else
11796                         {
11797                                 for (j = 0;j < surfacenumvertices;j++)
11798                                 {
11799                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11800                                         numvertices++;
11801                                 }
11802                         }
11803                 }
11804         }
11805
11806         // if vertices are deformed (sprite flares and things in maps, possibly
11807         // water waves, bulges and other deformations), modify the copied vertices
11808         // in place
11809         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11810         {
11811                 switch (deform->deform)
11812                 {
11813                 default:
11814                 case Q3DEFORM_PROJECTIONSHADOW:
11815                 case Q3DEFORM_TEXT0:
11816                 case Q3DEFORM_TEXT1:
11817                 case Q3DEFORM_TEXT2:
11818                 case Q3DEFORM_TEXT3:
11819                 case Q3DEFORM_TEXT4:
11820                 case Q3DEFORM_TEXT5:
11821                 case Q3DEFORM_TEXT6:
11822                 case Q3DEFORM_TEXT7:
11823                 case Q3DEFORM_NONE:
11824                         break;
11825                 case Q3DEFORM_AUTOSPRITE:
11826                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11827                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11828                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11829                         VectorNormalize(newforward);
11830                         VectorNormalize(newright);
11831                         VectorNormalize(newup);
11832                         // a single autosprite surface can contain multiple sprites...
11833                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11834                         {
11835                                 VectorClear(center);
11836                                 for (i = 0;i < 4;i++)
11837                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11838                                 VectorScale(center, 0.25f, center);
11839                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11840                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11841                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11842                                 for (i = 0;i < 4;i++)
11843                                 {
11844                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11845                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11846                                 }
11847                         }
11848                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11849                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11850                         Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
11851                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11852                         rsurface.batchvertex3f_vertexbuffer = NULL;
11853                         rsurface.batchvertex3f_bufferoffset = 0;
11854                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11855                         rsurface.batchsvector3f_vertexbuffer = NULL;
11856                         rsurface.batchsvector3f_bufferoffset = 0;
11857                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11858                         rsurface.batchtvector3f_vertexbuffer = NULL;
11859                         rsurface.batchtvector3f_bufferoffset = 0;
11860                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11861                         rsurface.batchnormal3f_vertexbuffer = NULL;
11862                         rsurface.batchnormal3f_bufferoffset = 0;
11863                         break;
11864                 case Q3DEFORM_AUTOSPRITE2:
11865                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11866                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11867                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11868                         VectorNormalize(newforward);
11869                         VectorNormalize(newright);
11870                         VectorNormalize(newup);
11871                         {
11872                                 const float *v1, *v2;
11873                                 vec3_t start, end;
11874                                 float f, l;
11875                                 struct
11876                                 {
11877                                         float length2;
11878                                         const float *v1;
11879                                         const float *v2;
11880                                 }
11881                                 shortest[2];
11882                                 memset(shortest, 0, sizeof(shortest));
11883                                 // a single autosprite surface can contain multiple sprites...
11884                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11885                                 {
11886                                         VectorClear(center);
11887                                         for (i = 0;i < 4;i++)
11888                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11889                                         VectorScale(center, 0.25f, center);
11890                                         // find the two shortest edges, then use them to define the
11891                                         // axis vectors for rotating around the central axis
11892                                         for (i = 0;i < 6;i++)
11893                                         {
11894                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11895                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11896                                                 l = VectorDistance2(v1, v2);
11897                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11898                                                 if (v1[2] != v2[2])
11899                                                         l += (1.0f / 1024.0f);
11900                                                 if (shortest[0].length2 > l || i == 0)
11901                                                 {
11902                                                         shortest[1] = shortest[0];
11903                                                         shortest[0].length2 = l;
11904                                                         shortest[0].v1 = v1;
11905                                                         shortest[0].v2 = v2;
11906                                                 }
11907                                                 else if (shortest[1].length2 > l || i == 1)
11908                                                 {
11909                                                         shortest[1].length2 = l;
11910                                                         shortest[1].v1 = v1;
11911                                                         shortest[1].v2 = v2;
11912                                                 }
11913                                         }
11914                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11915                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11916                                         // this calculates the right vector from the shortest edge
11917                                         // and the up vector from the edge midpoints
11918                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11919                                         VectorNormalize(right);
11920                                         VectorSubtract(end, start, up);
11921                                         VectorNormalize(up);
11922                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11923                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11924                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11925                                         VectorNegate(forward, forward);
11926                                         VectorReflect(forward, 0, up, forward);
11927                                         VectorNormalize(forward);
11928                                         CrossProduct(up, forward, newright);
11929                                         VectorNormalize(newright);
11930                                         // rotate the quad around the up axis vector, this is made
11931                                         // especially easy by the fact we know the quad is flat,
11932                                         // so we only have to subtract the center position and
11933                                         // measure distance along the right vector, and then
11934                                         // multiply that by the newright vector and add back the
11935                                         // center position
11936                                         // we also need to subtract the old position to undo the
11937                                         // displacement from the center, which we do with a
11938                                         // DotProduct, the subtraction/addition of center is also
11939                                         // optimized into DotProducts here
11940                                         l = DotProduct(right, center);
11941                                         for (i = 0;i < 4;i++)
11942                                         {
11943                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11944                                                 f = DotProduct(right, v1) - l;
11945                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11946                                         }
11947                                 }
11948                         }
11949                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11950                         rsurface.batchvertex3f_vertexbuffer = NULL;
11951                         rsurface.batchvertex3f_bufferoffset = 0;
11952                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11953                         {
11954                                 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11955                                 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11956                                 rsurface.batchnormal3f_vertexbuffer = NULL;
11957                                 rsurface.batchnormal3f_bufferoffset = 0;
11958                         }
11959                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11960                         {
11961                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
11962                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11963                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11964                                 rsurface.batchsvector3f_bufferoffset = 0;
11965                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11966                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11967                                 rsurface.batchtvector3f_bufferoffset = 0;
11968                         }
11969                         break;
11970                 case Q3DEFORM_NORMAL:
11971                         // deform the normals to make reflections wavey
11972                         for (j = 0;j < rsurface.batchnumvertices;j++)
11973                         {
11974                                 float vertex[3];
11975                                 float *normal = rsurface.array_batchnormal3f + 3*j;
11976                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11977                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11978                                 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]);
11979                                 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]);
11980                                 VectorNormalize(normal);
11981                         }
11982                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11983                         rsurface.batchnormal3f_vertexbuffer = NULL;
11984                         rsurface.batchnormal3f_bufferoffset = 0;
11985                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11986                         {
11987                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
11988                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11989                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11990                                 rsurface.batchsvector3f_bufferoffset = 0;
11991                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11992                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11993                                 rsurface.batchtvector3f_bufferoffset = 0;
11994                         }
11995                         break;
11996                 case Q3DEFORM_WAVE:
11997                         // deform vertex array to make wavey water and flags and such
11998                         waveparms[0] = deform->waveparms[0];
11999                         waveparms[1] = deform->waveparms[1];
12000                         waveparms[2] = deform->waveparms[2];
12001                         waveparms[3] = deform->waveparms[3];
12002                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
12003                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12004                         // this is how a divisor of vertex influence on deformation
12005                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
12006                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12007                         for (j = 0;j < rsurface.batchnumvertices;j++)
12008                         {
12009                                 // if the wavefunc depends on time, evaluate it per-vertex
12010                                 if (waveparms[3])
12011                                 {
12012                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
12013                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12014                                 }
12015                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
12016                         }
12017                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12018                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
12019                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12020                         rsurface.batchvertex3f_vertexbuffer = NULL;
12021                         rsurface.batchvertex3f_bufferoffset = 0;
12022                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12023                         rsurface.batchnormal3f_vertexbuffer = NULL;
12024                         rsurface.batchnormal3f_bufferoffset = 0;
12025                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12026                         {
12027                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
12028                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12029                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12030                                 rsurface.batchsvector3f_bufferoffset = 0;
12031                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12032                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12033                                 rsurface.batchtvector3f_bufferoffset = 0;
12034                         }
12035                         break;
12036                 case Q3DEFORM_BULGE:
12037                         // deform vertex array to make the surface have moving bulges
12038                         for (j = 0;j < rsurface.batchnumvertices;j++)
12039                         {
12040                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
12041                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
12042                         }
12043                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12044                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
12045                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12046                         rsurface.batchvertex3f_vertexbuffer = NULL;
12047                         rsurface.batchvertex3f_bufferoffset = 0;
12048                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12049                         rsurface.batchnormal3f_vertexbuffer = NULL;
12050                         rsurface.batchnormal3f_bufferoffset = 0;
12051                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12052                         {
12053                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
12054                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12055                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12056                                 rsurface.batchsvector3f_bufferoffset = 0;
12057                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12058                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12059                                 rsurface.batchtvector3f_bufferoffset = 0;
12060                         }
12061                         break;
12062                 case Q3DEFORM_MOVE:
12063                         // deform vertex array
12064                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12065                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12066                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
12067                         VectorScale(deform->parms, scale, waveparms);
12068                         for (j = 0;j < rsurface.batchnumvertices;j++)
12069                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
12070                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12071                         rsurface.batchvertex3f_vertexbuffer = NULL;
12072                         rsurface.batchvertex3f_bufferoffset = 0;
12073                         break;
12074                 }
12075         }
12076
12077         // generate texcoords based on the chosen texcoord source
12078         switch(rsurface.texture->tcgen.tcgen)
12079         {
12080         default:
12081         case Q3TCGEN_TEXTURE:
12082                 break;
12083         case Q3TCGEN_LIGHTMAP:
12084                 if (rsurface.batchtexcoordlightmap2f)
12085                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
12086                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12087                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12088                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12089                 break;
12090         case Q3TCGEN_VECTOR:
12091                 for (j = 0;j < rsurface.batchnumvertices;j++)
12092                 {
12093                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12094                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12095                 }
12096                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12097                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12098                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12099                 break;
12100         case Q3TCGEN_ENVIRONMENT:
12101                 // make environment reflections using a spheremap
12102                 for (j = 0;j < rsurface.batchnumvertices;j++)
12103                 {
12104                         // identical to Q3A's method, but executed in worldspace so
12105                         // carried models can be shiny too
12106
12107                         float viewer[3], d, reflected[3], worldreflected[3];
12108
12109                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12110                         // VectorNormalize(viewer);
12111
12112                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12113
12114                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12115                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12116                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12117                         // note: this is proportinal to viewer, so we can normalize later
12118
12119                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12120                         VectorNormalize(worldreflected);
12121
12122                         // note: this sphere map only uses world x and z!
12123                         // so positive and negative y will LOOK THE SAME.
12124                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12125                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12126                 }
12127                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12128                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12129                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12130                 break;
12131         }
12132         // the only tcmod that needs software vertex processing is turbulent, so
12133         // check for it here and apply the changes if needed
12134         // and we only support that as the first one
12135         // (handling a mixture of turbulent and other tcmods would be problematic
12136         //  without punting it entirely to a software path)
12137         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12138         {
12139                 amplitude = rsurface.texture->tcmods[0].parms[1];
12140                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12141                 for (j = 0;j < rsurface.batchnumvertices;j++)
12142                 {
12143                         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);
12144                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12145                 }
12146                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12147                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12148                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12149         }
12150
12151         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12152         {
12153                 // convert the modified arrays to vertex structs
12154                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
12155                 rsurface.batchvertexmeshbuffer = NULL;
12156                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12157                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12158                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12159                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12160                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12161                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12162                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12163                 {
12164                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12165                         {
12166                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12167                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12168                         }
12169                 }
12170                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12171                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12172                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12173                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12174                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12175                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12176                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12177                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12178                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12179         }
12180
12181         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
12182         {
12183                 // convert the modified arrays to vertex structs
12184                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
12185                 rsurface.batchvertexpositionbuffer = NULL;
12186                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
12187                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
12188                 else
12189                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
12190                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
12191         }
12192 }
12193
12194 void RSurf_DrawBatch(void)
12195 {
12196         // sometimes a zero triangle surface (usually a degenerate patch) makes it
12197         // through the pipeline, killing it earlier in the pipeline would have
12198         // per-surface overhead rather than per-batch overhead, so it's best to
12199         // reject it here, before it hits glDraw.
12200         if (rsurface.batchnumtriangles == 0)
12201                 return;
12202 #if 0
12203         // batch debugging code
12204         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
12205         {
12206                 int i;
12207                 int j;
12208                 int c;
12209                 const int *e;
12210                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
12211                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
12212                 {
12213                         c = e[i];
12214                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
12215                         {
12216                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
12217                                 {
12218                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
12219                                                 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);
12220                                         break;
12221                                 }
12222                         }
12223                 }
12224         }
12225 #endif
12226         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);
12227 }
12228
12229 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12230 {
12231         // pick the closest matching water plane
12232         int planeindex, vertexindex, bestplaneindex = -1;
12233         float d, bestd;
12234         vec3_t vert;
12235         const float *v;
12236         r_waterstate_waterplane_t *p;
12237         bestd = 0;
12238         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12239         {
12240                 if(p->camera_entity != rsurface.texture->camera_entity)
12241                         continue;
12242                 d = 0;
12243                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
12244                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12245                 {
12246                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
12247                         d += fabs(PlaneDiff(vert, &p->plane));
12248                 }
12249                 if (bestd > d || bestplaneindex < 0)
12250                 {
12251                         bestd = d;
12252                         bestplaneindex = planeindex;
12253                 }
12254         }
12255         return bestplaneindex;
12256 }
12257
12258 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12259 {
12260         int i;
12261         for (i = 0;i < rsurface.batchnumvertices;i++)
12262                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12263         rsurface.passcolor4f = rsurface.array_passcolor4f;
12264         rsurface.passcolor4f_vertexbuffer = 0;
12265         rsurface.passcolor4f_bufferoffset = 0;
12266 }
12267
12268 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12269 {
12270         int i;
12271         float f;
12272         const float *v;
12273         const float *c;
12274         float *c2;
12275         if (rsurface.passcolor4f)
12276         {
12277                 // generate color arrays
12278                 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)
12279                 {
12280                         f = RSurf_FogVertex(v);
12281                         c2[0] = c[0] * f;
12282                         c2[1] = c[1] * f;
12283                         c2[2] = c[2] * f;
12284                         c2[3] = c[3];
12285                 }
12286         }
12287         else
12288         {
12289                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12290                 {
12291                         f = RSurf_FogVertex(v);
12292                         c2[0] = f;
12293                         c2[1] = f;
12294                         c2[2] = f;
12295                         c2[3] = 1;
12296                 }
12297         }
12298         rsurface.passcolor4f = rsurface.array_passcolor4f;
12299         rsurface.passcolor4f_vertexbuffer = 0;
12300         rsurface.passcolor4f_bufferoffset = 0;
12301 }
12302
12303 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12304 {
12305         int i;
12306         float f;
12307         const float *v;
12308         const float *c;
12309         float *c2;
12310         if (!rsurface.passcolor4f)
12311                 return;
12312         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)
12313         {
12314                 f = RSurf_FogVertex(v);
12315                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12316                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12317                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12318                 c2[3] = c[3];
12319         }
12320         rsurface.passcolor4f = rsurface.array_passcolor4f;
12321         rsurface.passcolor4f_vertexbuffer = 0;
12322         rsurface.passcolor4f_bufferoffset = 0;
12323 }
12324
12325 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12326 {
12327         int i;
12328         const float *c;
12329         float *c2;
12330         if (!rsurface.passcolor4f)
12331                 return;
12332         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12333         {
12334                 c2[0] = c[0] * r;
12335                 c2[1] = c[1] * g;
12336                 c2[2] = c[2] * b;
12337                 c2[3] = c[3] * a;
12338         }
12339         rsurface.passcolor4f = rsurface.array_passcolor4f;
12340         rsurface.passcolor4f_vertexbuffer = 0;
12341         rsurface.passcolor4f_bufferoffset = 0;
12342 }
12343
12344 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12345 {
12346         int i;
12347         const float *c;
12348         float *c2;
12349         if (!rsurface.passcolor4f)
12350                 return;
12351         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12352         {
12353                 c2[0] = c[0] + r_refdef.scene.ambient;
12354                 c2[1] = c[1] + r_refdef.scene.ambient;
12355                 c2[2] = c[2] + r_refdef.scene.ambient;
12356                 c2[3] = c[3];
12357         }
12358         rsurface.passcolor4f = rsurface.array_passcolor4f;
12359         rsurface.passcolor4f_vertexbuffer = 0;
12360         rsurface.passcolor4f_bufferoffset = 0;
12361 }
12362
12363 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12364 {
12365         // TODO: optimize
12366         rsurface.passcolor4f = NULL;
12367         rsurface.passcolor4f_vertexbuffer = 0;
12368         rsurface.passcolor4f_bufferoffset = 0;
12369         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12370         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12371         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12372         GL_Color(r, g, b, a);
12373         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12374         RSurf_DrawBatch();
12375 }
12376
12377 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12378 {
12379         // TODO: optimize applyfog && applycolor case
12380         // just apply fog if necessary, and tint the fog color array if necessary
12381         rsurface.passcolor4f = NULL;
12382         rsurface.passcolor4f_vertexbuffer = 0;
12383         rsurface.passcolor4f_bufferoffset = 0;
12384         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12385         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12386         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12387         GL_Color(r, g, b, a);
12388         RSurf_DrawBatch();
12389 }
12390
12391 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12392 {
12393         // TODO: optimize
12394         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12395         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12396         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12397         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12398         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12399         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12400         GL_Color(r, g, b, a);
12401         RSurf_DrawBatch();
12402 }
12403
12404 static void RSurf_DrawBatch_GL11_ClampColor(void)
12405 {
12406         int i;
12407         const float *c1;
12408         float *c2;
12409         if (!rsurface.passcolor4f)
12410                 return;
12411         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12412         {
12413                 c2[0] = bound(0.0f, c1[0], 1.0f);
12414                 c2[1] = bound(0.0f, c1[1], 1.0f);
12415                 c2[2] = bound(0.0f, c1[2], 1.0f);
12416                 c2[3] = bound(0.0f, c1[3], 1.0f);
12417         }
12418 }
12419
12420 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12421 {
12422         int i;
12423         float f;
12424         const float *v;
12425         const float *n;
12426         float *c;
12427         //vec3_t eyedir;
12428
12429         // fake shading
12430         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)
12431         {
12432                 f = -DotProduct(r_refdef.view.forward, n);
12433                 f = max(0, f);
12434                 f = f * 0.85 + 0.15; // work around so stuff won't get black
12435                 f *= r_refdef.lightmapintensity;
12436                 Vector4Set(c, f, f, f, 1);
12437         }
12438
12439         rsurface.passcolor4f = rsurface.array_passcolor4f;
12440         rsurface.passcolor4f_vertexbuffer = 0;
12441         rsurface.passcolor4f_bufferoffset = 0;
12442 }
12443
12444 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12445 {
12446         RSurf_DrawBatch_GL11_ApplyFakeLight();
12447         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12448         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12449         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12450         GL_Color(r, g, b, a);
12451         RSurf_DrawBatch();
12452 }
12453
12454 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12455 {
12456         int i;
12457         float f;
12458         float alpha;
12459         const float *v;
12460         const float *n;
12461         float *c;
12462         vec3_t ambientcolor;
12463         vec3_t diffusecolor;
12464         vec3_t lightdir;
12465         // TODO: optimize
12466         // model lighting
12467         VectorCopy(rsurface.modellight_lightdir, lightdir);
12468         f = 0.5f * r_refdef.lightmapintensity;
12469         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12470         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12471         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12472         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12473         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12474         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12475         alpha = *a;
12476         if (VectorLength2(diffusecolor) > 0)
12477         {
12478                 // q3-style directional shading
12479                 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)
12480                 {
12481                         if ((f = DotProduct(n, lightdir)) > 0)
12482                                 VectorMA(ambientcolor, f, diffusecolor, c);
12483                         else
12484                                 VectorCopy(ambientcolor, c);
12485                         c[3] = alpha;
12486                 }
12487                 *r = 1;
12488                 *g = 1;
12489                 *b = 1;
12490                 *a = 1;
12491                 rsurface.passcolor4f = rsurface.array_passcolor4f;
12492                 rsurface.passcolor4f_vertexbuffer = 0;
12493                 rsurface.passcolor4f_bufferoffset = 0;
12494                 *applycolor = false;
12495         }
12496         else
12497         {
12498                 *r = ambientcolor[0];
12499                 *g = ambientcolor[1];
12500                 *b = ambientcolor[2];
12501                 rsurface.passcolor4f = NULL;
12502                 rsurface.passcolor4f_vertexbuffer = 0;
12503                 rsurface.passcolor4f_bufferoffset = 0;
12504         }
12505 }
12506
12507 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12508 {
12509         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12510         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12511         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12512         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12513         GL_Color(r, g, b, a);
12514         RSurf_DrawBatch();
12515 }
12516
12517 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12518 {
12519         int i;
12520         float f;
12521         const float *v;
12522         float *c;
12523         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12524         {
12525                 f = 1 - RSurf_FogVertex(v);
12526                 c[0] = r;
12527                 c[1] = g;
12528                 c[2] = b;
12529                 c[3] = f * a;
12530         }
12531 }
12532
12533 void RSurf_SetupDepthAndCulling(void)
12534 {
12535         // submodels are biased to avoid z-fighting with world surfaces that they
12536         // may be exactly overlapping (avoids z-fighting artifacts on certain
12537         // doors and things in Quake maps)
12538         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12539         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12540         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12541         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12542 }
12543
12544 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12545 {
12546         // transparent sky would be ridiculous
12547         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12548                 return;
12549         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12550         skyrenderlater = true;
12551         RSurf_SetupDepthAndCulling();
12552         GL_DepthMask(true);
12553         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12554         // skymasking on them, and Quake3 never did sky masking (unlike
12555         // software Quake and software Quake2), so disable the sky masking
12556         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12557         // and skymasking also looks very bad when noclipping outside the
12558         // level, so don't use it then either.
12559         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12560         {
12561                 R_Mesh_ResetTextureState();
12562                 if (skyrendermasked)
12563                 {
12564                         R_SetupShader_DepthOrShadow();
12565                         // depth-only (masking)
12566                         GL_ColorMask(0,0,0,0);
12567                         // just to make sure that braindead drivers don't draw
12568                         // anything despite that colormask...
12569                         GL_BlendFunc(GL_ZERO, GL_ONE);
12570                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12571                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12572                 }
12573                 else
12574                 {
12575                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12576                         // fog sky
12577                         GL_BlendFunc(GL_ONE, GL_ZERO);
12578                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12579                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12580                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12581                 }
12582                 RSurf_DrawBatch();
12583                 if (skyrendermasked)
12584                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12585         }
12586         R_Mesh_ResetTextureState();
12587         GL_Color(1, 1, 1, 1);
12588 }
12589
12590 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12591 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12592 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12593 {
12594         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12595                 return;
12596         if (prepass)
12597         {
12598                 // render screenspace normalmap to texture
12599                 GL_DepthMask(true);
12600                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12601                 RSurf_DrawBatch();
12602                 return;
12603         }
12604
12605         // bind lightmap texture
12606
12607         // water/refraction/reflection/camera surfaces have to be handled specially
12608         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12609         {
12610                 int start, end, startplaneindex;
12611                 for (start = 0;start < texturenumsurfaces;start = end)
12612                 {
12613                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12614                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12615                                 ;
12616                         // now that we have a batch using the same planeindex, render it
12617                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12618                         {
12619                                 // render water or distortion background
12620                                 GL_DepthMask(true);
12621                                 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));
12622                                 RSurf_DrawBatch();
12623                                 // blend surface on top
12624                                 GL_DepthMask(false);
12625                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12626                                 RSurf_DrawBatch();
12627                         }
12628                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12629                         {
12630                                 // render surface with reflection texture as input
12631                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12632                                 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));
12633                                 RSurf_DrawBatch();
12634                         }
12635                 }
12636                 return;
12637         }
12638
12639         // render surface batch normally
12640         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12641         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12642         RSurf_DrawBatch();
12643 }
12644
12645 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12646 {
12647         // OpenGL 1.3 path - anything not completely ancient
12648         qboolean applycolor;
12649         qboolean applyfog;
12650         int layerindex;
12651         const texturelayer_t *layer;
12652         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);
12653         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12654
12655         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12656         {
12657                 vec4_t layercolor;
12658                 int layertexrgbscale;
12659                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12660                 {
12661                         if (layerindex == 0)
12662                                 GL_AlphaTest(true);
12663                         else
12664                         {
12665                                 GL_AlphaTest(false);
12666                                 GL_DepthFunc(GL_EQUAL);
12667                         }
12668                 }
12669                 GL_DepthMask(layer->depthmask && writedepth);
12670                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12671                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12672                 {
12673                         layertexrgbscale = 4;
12674                         VectorScale(layer->color, 0.25f, layercolor);
12675                 }
12676                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12677                 {
12678                         layertexrgbscale = 2;
12679                         VectorScale(layer->color, 0.5f, layercolor);
12680                 }
12681                 else
12682                 {
12683                         layertexrgbscale = 1;
12684                         VectorScale(layer->color, 1.0f, layercolor);
12685                 }
12686                 layercolor[3] = layer->color[3];
12687                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12688                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12689                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12690                 switch (layer->type)
12691                 {
12692                 case TEXTURELAYERTYPE_LITTEXTURE:
12693                         // single-pass lightmapped texture with 2x rgbscale
12694                         R_Mesh_TexBind(0, r_texture_white);
12695                         R_Mesh_TexMatrix(0, NULL);
12696                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12697                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12698                         R_Mesh_TexBind(1, layer->texture);
12699                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12700                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12701                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12702                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12703                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12704                         else if (FAKELIGHT_ENABLED)
12705                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12706                         else if (rsurface.uselightmaptexture)
12707                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12708                         else
12709                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12710                         break;
12711                 case TEXTURELAYERTYPE_TEXTURE:
12712                         // singletexture unlit texture with transparency support
12713                         R_Mesh_TexBind(0, layer->texture);
12714                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12715                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12716                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12717                         R_Mesh_TexBind(1, 0);
12718                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12719                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12720                         break;
12721                 case TEXTURELAYERTYPE_FOG:
12722                         // singletexture fogging
12723                         if (layer->texture)
12724                         {
12725                                 R_Mesh_TexBind(0, layer->texture);
12726                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12727                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12728                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12729                         }
12730                         else
12731                         {
12732                                 R_Mesh_TexBind(0, 0);
12733                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12734                         }
12735                         R_Mesh_TexBind(1, 0);
12736                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12737                         // generate a color array for the fog pass
12738                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12739                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12740                         RSurf_DrawBatch();
12741                         break;
12742                 default:
12743                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12744                 }
12745         }
12746         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12747         {
12748                 GL_DepthFunc(GL_LEQUAL);
12749                 GL_AlphaTest(false);
12750         }
12751 }
12752
12753 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12754 {
12755         // OpenGL 1.1 - crusty old voodoo path
12756         qboolean applyfog;
12757         int layerindex;
12758         const texturelayer_t *layer;
12759         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);
12760         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12761
12762         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12763         {
12764                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12765                 {
12766                         if (layerindex == 0)
12767                                 GL_AlphaTest(true);
12768                         else
12769                         {
12770                                 GL_AlphaTest(false);
12771                                 GL_DepthFunc(GL_EQUAL);
12772                         }
12773                 }
12774                 GL_DepthMask(layer->depthmask && writedepth);
12775                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12776                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12777                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12778                 switch (layer->type)
12779                 {
12780                 case TEXTURELAYERTYPE_LITTEXTURE:
12781                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12782                         {
12783                                 // two-pass lit texture with 2x rgbscale
12784                                 // first the lightmap pass
12785                                 R_Mesh_TexBind(0, r_texture_white);
12786                                 R_Mesh_TexMatrix(0, NULL);
12787                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12788                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12789                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12790                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12791                                 else if (FAKELIGHT_ENABLED)
12792                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12793                                 else if (rsurface.uselightmaptexture)
12794                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12795                                 else
12796                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12797                                 // then apply the texture to it
12798                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12799                                 R_Mesh_TexBind(0, layer->texture);
12800                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12801                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12802                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12803                                 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);
12804                         }
12805                         else
12806                         {
12807                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12808                                 R_Mesh_TexBind(0, layer->texture);
12809                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12810                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12811                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12812                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12813                                         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);
12814                                 else
12815                                         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);
12816                         }
12817                         break;
12818                 case TEXTURELAYERTYPE_TEXTURE:
12819                         // singletexture unlit texture with transparency support
12820                         R_Mesh_TexBind(0, layer->texture);
12821                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12822                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12823                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12824                         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);
12825                         break;
12826                 case TEXTURELAYERTYPE_FOG:
12827                         // singletexture fogging
12828                         if (layer->texture)
12829                         {
12830                                 R_Mesh_TexBind(0, layer->texture);
12831                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12832                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12833                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12834                         }
12835                         else
12836                         {
12837                                 R_Mesh_TexBind(0, 0);
12838                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12839                         }
12840                         // generate a color array for the fog pass
12841                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12842                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12843                         RSurf_DrawBatch();
12844                         break;
12845                 default:
12846                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12847                 }
12848         }
12849         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12850         {
12851                 GL_DepthFunc(GL_LEQUAL);
12852                 GL_AlphaTest(false);
12853         }
12854 }
12855
12856 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12857 {
12858         int vi;
12859         int j;
12860         r_vertexgeneric_t *batchvertex;
12861         float c[4];
12862
12863         GL_AlphaTest(false);
12864 //      R_Mesh_ResetTextureState();
12865         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12866
12867         if(rsurface.texture && rsurface.texture->currentskinframe)
12868         {
12869                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12870                 c[3] *= rsurface.texture->currentalpha;
12871         }
12872         else
12873         {
12874                 c[0] = 1;
12875                 c[1] = 0;
12876                 c[2] = 1;
12877                 c[3] = 1;
12878         }
12879
12880         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12881         {
12882                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12883                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12884                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12885         }
12886
12887         // brighten it up (as texture value 127 means "unlit")
12888         c[0] *= 2 * r_refdef.view.colorscale;
12889         c[1] *= 2 * r_refdef.view.colorscale;
12890         c[2] *= 2 * r_refdef.view.colorscale;
12891
12892         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12893                 c[3] *= r_wateralpha.value;
12894
12895         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12896         {
12897                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12898                 GL_DepthMask(false);
12899         }
12900         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12901         {
12902                 GL_BlendFunc(GL_ONE, GL_ONE);
12903                 GL_DepthMask(false);
12904         }
12905         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12906         {
12907                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12908                 GL_DepthMask(false);
12909         }
12910         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12911         {
12912                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12913                 GL_DepthMask(false);
12914         }
12915         else
12916         {
12917                 GL_BlendFunc(GL_ONE, GL_ZERO);
12918                 GL_DepthMask(writedepth);
12919         }
12920
12921         if (r_showsurfaces.integer == 3)
12922         {
12923                 rsurface.passcolor4f = NULL;
12924
12925                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12926                 {
12927                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12928
12929                         rsurface.passcolor4f = NULL;
12930                         rsurface.passcolor4f_vertexbuffer = 0;
12931                         rsurface.passcolor4f_bufferoffset = 0;
12932                 }
12933                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12934                 {
12935                         qboolean applycolor = true;
12936                         float one = 1.0;
12937
12938                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12939
12940                         r_refdef.lightmapintensity = 1;
12941                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12942                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12943                 }
12944                 else if (FAKELIGHT_ENABLED)
12945                 {
12946                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12947
12948                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
12949                         RSurf_DrawBatch_GL11_ApplyFakeLight();
12950                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12951                 }
12952                 else
12953                 {
12954                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12955
12956                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12957                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12958                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12959                 }
12960
12961                 if(!rsurface.passcolor4f)
12962                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12963
12964                 RSurf_DrawBatch_GL11_ApplyAmbient();
12965                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12966                 if(r_refdef.fogenabled)
12967                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12968                 RSurf_DrawBatch_GL11_ClampColor();
12969
12970                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12971                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12972                 RSurf_DrawBatch();
12973         }
12974         else if (!r_refdef.view.showdebug)
12975         {
12976                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12977                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12978                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12979                 {
12980                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12981                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12982                 }
12983                 R_Mesh_PrepareVertices_Generic_Unlock();
12984                 RSurf_DrawBatch();
12985         }
12986         else if (r_showsurfaces.integer == 4)
12987         {
12988                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12989                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12990                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12991                 {
12992                         unsigned char c = vi << 3;
12993                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12994                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12995                 }
12996                 R_Mesh_PrepareVertices_Generic_Unlock();
12997                 RSurf_DrawBatch();
12998         }
12999         else if (r_showsurfaces.integer == 2)
13000         {
13001                 const int *e;
13002                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13003                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
13004                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
13005                 {
13006                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
13007                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
13008                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
13009                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
13010                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
13011                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
13012                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
13013                 }
13014                 R_Mesh_PrepareVertices_Generic_Unlock();
13015                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
13016         }
13017         else
13018         {
13019                 int texturesurfaceindex;
13020                 int k;
13021                 const msurface_t *surface;
13022                 unsigned char surfacecolor4ub[4];
13023                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13024                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
13025                 vi = 0;
13026                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
13027                 {
13028                         surface = texturesurfacelist[texturesurfaceindex];
13029                         k = (int)(((size_t)surface) / sizeof(msurface_t));
13030                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
13031                         for (j = 0;j < surface->num_vertices;j++)
13032                         {
13033                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13034                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
13035                                 vi++;
13036                         }
13037                 }
13038                 R_Mesh_PrepareVertices_Generic_Unlock();
13039                 RSurf_DrawBatch();
13040         }
13041 }
13042
13043 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13044 {
13045         CHECKGLERROR
13046         RSurf_SetupDepthAndCulling();
13047         if (r_showsurfaces.integer)
13048         {
13049                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13050                 return;
13051         }
13052         switch (vid.renderpath)
13053         {
13054         case RENDERPATH_GL20:
13055         case RENDERPATH_CGGL:
13056         case RENDERPATH_D3D9:
13057         case RENDERPATH_D3D10:
13058         case RENDERPATH_D3D11:
13059                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13060                 break;
13061         case RENDERPATH_GL13:
13062                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13063                 break;
13064         case RENDERPATH_GL11:
13065                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13066                 break;
13067         }
13068         CHECKGLERROR
13069 }
13070
13071 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13072 {
13073         CHECKGLERROR
13074         RSurf_SetupDepthAndCulling();
13075         if (r_showsurfaces.integer)
13076         {
13077                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13078                 return;
13079         }
13080         switch (vid.renderpath)
13081         {
13082         case RENDERPATH_GL20:
13083         case RENDERPATH_CGGL:
13084         case RENDERPATH_D3D9:
13085         case RENDERPATH_D3D10:
13086         case RENDERPATH_D3D11:
13087                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13088                 break;
13089         case RENDERPATH_GL13:
13090                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13091                 break;
13092         case RENDERPATH_GL11:
13093                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13094                 break;
13095         }
13096         CHECKGLERROR
13097 }
13098
13099 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13100 {
13101         int i, j;
13102         int texturenumsurfaces, endsurface;
13103         texture_t *texture;
13104         const msurface_t *surface;
13105 #define MAXBATCH_TRANSPARENTSURFACES 256
13106         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13107
13108         // if the model is static it doesn't matter what value we give for
13109         // wantnormals and wanttangents, so this logic uses only rules applicable
13110         // to a model, knowing that they are meaningless otherwise
13111         if (ent == r_refdef.scene.worldentity)
13112                 RSurf_ActiveWorldEntity();
13113         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13114                 RSurf_ActiveModelEntity(ent, false, false, false);
13115         else
13116         {
13117                 switch (vid.renderpath)
13118                 {
13119                 case RENDERPATH_GL20:
13120                 case RENDERPATH_CGGL:
13121                 case RENDERPATH_D3D9:
13122                 case RENDERPATH_D3D10:
13123                 case RENDERPATH_D3D11:
13124                         RSurf_ActiveModelEntity(ent, true, true, false);
13125                         break;
13126                 case RENDERPATH_GL13:
13127                 case RENDERPATH_GL11:
13128                         RSurf_ActiveModelEntity(ent, true, false, false);
13129                         break;
13130                 }
13131         }
13132
13133         if (r_transparentdepthmasking.integer)
13134         {
13135                 qboolean setup = false;
13136                 for (i = 0;i < numsurfaces;i = j)
13137                 {
13138                         j = i + 1;
13139                         surface = rsurface.modelsurfaces + surfacelist[i];
13140                         texture = surface->texture;
13141                         rsurface.texture = R_GetCurrentTexture(texture);
13142                         rsurface.lightmaptexture = NULL;
13143                         rsurface.deluxemaptexture = NULL;
13144                         rsurface.uselightmaptexture = false;
13145                         // scan ahead until we find a different texture
13146                         endsurface = min(i + 1024, numsurfaces);
13147                         texturenumsurfaces = 0;
13148                         texturesurfacelist[texturenumsurfaces++] = surface;
13149                         for (;j < endsurface;j++)
13150                         {
13151                                 surface = rsurface.modelsurfaces + surfacelist[j];
13152                                 if (texture != surface->texture)
13153                                         break;
13154                                 texturesurfacelist[texturenumsurfaces++] = surface;
13155                         }
13156                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13157                                 continue;
13158                         // render the range of surfaces as depth
13159                         if (!setup)
13160                         {
13161                                 setup = true;
13162                                 GL_ColorMask(0,0,0,0);
13163                                 GL_Color(1,1,1,1);
13164                                 GL_DepthTest(true);
13165                                 GL_BlendFunc(GL_ONE, GL_ZERO);
13166                                 GL_DepthMask(true);
13167                                 GL_AlphaTest(false);
13168 //                              R_Mesh_ResetTextureState();
13169                                 R_SetupShader_DepthOrShadow();
13170                         }
13171                         RSurf_SetupDepthAndCulling();
13172                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13173                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13174                         RSurf_DrawBatch();
13175                 }
13176                 if (setup)
13177                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13178         }
13179
13180         for (i = 0;i < numsurfaces;i = j)
13181         {
13182                 j = i + 1;
13183                 surface = rsurface.modelsurfaces + surfacelist[i];
13184                 texture = surface->texture;
13185                 rsurface.texture = R_GetCurrentTexture(texture);
13186                 // scan ahead until we find a different texture
13187                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13188                 texturenumsurfaces = 0;
13189                 texturesurfacelist[texturenumsurfaces++] = surface;
13190                 if(FAKELIGHT_ENABLED)
13191                 {
13192                         rsurface.lightmaptexture = NULL;
13193                         rsurface.deluxemaptexture = NULL;
13194                         rsurface.uselightmaptexture = false;
13195                         for (;j < endsurface;j++)
13196                         {
13197                                 surface = rsurface.modelsurfaces + surfacelist[j];
13198                                 if (texture != surface->texture)
13199                                         break;
13200                                 texturesurfacelist[texturenumsurfaces++] = surface;
13201                         }
13202                 }
13203                 else
13204                 {
13205                         rsurface.lightmaptexture = surface->lightmaptexture;
13206                         rsurface.deluxemaptexture = surface->deluxemaptexture;
13207                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13208                         for (;j < endsurface;j++)
13209                         {
13210                                 surface = rsurface.modelsurfaces + surfacelist[j];
13211                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13212                                         break;
13213                                 texturesurfacelist[texturenumsurfaces++] = surface;
13214                         }
13215                 }
13216                 // render the range of surfaces
13217                 if (ent == r_refdef.scene.worldentity)
13218                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13219                 else
13220                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13221         }
13222         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13223         GL_AlphaTest(false);
13224 }
13225
13226 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13227 {
13228         // transparent surfaces get pushed off into the transparent queue
13229         int surfacelistindex;
13230         const msurface_t *surface;
13231         vec3_t tempcenter, center;
13232         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13233         {
13234                 surface = texturesurfacelist[surfacelistindex];
13235                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13236                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13237                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13238                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13239                 if (queueentity->transparent_offset) // transparent offset
13240                 {
13241                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13242                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13243                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13244                 }
13245                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13246         }
13247 }
13248
13249 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13250 {
13251         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13252                 return;
13253         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13254                 return;
13255         RSurf_SetupDepthAndCulling();
13256         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13257         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13258         RSurf_DrawBatch();
13259 }
13260
13261 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13262 {
13263         const entity_render_t *queueentity = r_refdef.scene.worldentity;
13264         CHECKGLERROR
13265         if (depthonly)
13266                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13267         else if (prepass)
13268         {
13269                 if (!rsurface.texture->currentnumlayers)
13270                         return;
13271                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13272                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13273                 else
13274                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13275         }
13276         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13277                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13278         else if (!rsurface.texture->currentnumlayers)
13279                 return;
13280         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13281         {
13282                 // in the deferred case, transparent surfaces were queued during prepass
13283                 if (!r_shadow_usingdeferredprepass)
13284                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13285         }
13286         else
13287         {
13288                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13289                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13290         }
13291         CHECKGLERROR
13292 }
13293
13294 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13295 {
13296         int i, j;
13297         texture_t *texture;
13298         // break the surface list down into batches by texture and use of lightmapping
13299         for (i = 0;i < numsurfaces;i = j)
13300         {
13301                 j = i + 1;
13302                 // texture is the base texture pointer, rsurface.texture is the
13303                 // current frame/skin the texture is directing us to use (for example
13304                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13305                 // use skin 1 instead)
13306                 texture = surfacelist[i]->texture;
13307                 rsurface.texture = R_GetCurrentTexture(texture);
13308                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13309                 {
13310                         // if this texture is not the kind we want, skip ahead to the next one
13311                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13312                                 ;
13313                         continue;
13314                 }
13315                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13316                 {
13317                         rsurface.lightmaptexture = NULL;
13318                         rsurface.deluxemaptexture = NULL;
13319                         rsurface.uselightmaptexture = false;
13320                         // simply scan ahead until we find a different texture or lightmap state
13321                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13322                                 ;
13323                 }
13324                 else
13325                 {
13326                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13327                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13328                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13329                         // simply scan ahead until we find a different texture or lightmap state
13330                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13331                                 ;
13332                 }
13333                 // render the range of surfaces
13334                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13335         }
13336 }
13337
13338 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13339 {
13340         CHECKGLERROR
13341         if (depthonly)
13342                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13343         else if (prepass)
13344         {
13345                 if (!rsurface.texture->currentnumlayers)
13346                         return;
13347                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13348                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13349                 else
13350                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13351         }
13352         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13353                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13354         else if (!rsurface.texture->currentnumlayers)
13355                 return;
13356         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13357         {
13358                 // in the deferred case, transparent surfaces were queued during prepass
13359                 if (!r_shadow_usingdeferredprepass)
13360                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13361         }
13362         else
13363         {
13364                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13365                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13366         }
13367         CHECKGLERROR
13368 }
13369
13370 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13371 {
13372         int i, j;
13373         texture_t *texture;
13374         // break the surface list down into batches by texture and use of lightmapping
13375         for (i = 0;i < numsurfaces;i = j)
13376         {
13377                 j = i + 1;
13378                 // texture is the base texture pointer, rsurface.texture is the
13379                 // current frame/skin the texture is directing us to use (for example
13380                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13381                 // use skin 1 instead)
13382                 texture = surfacelist[i]->texture;
13383                 rsurface.texture = R_GetCurrentTexture(texture);
13384                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13385                 {
13386                         // if this texture is not the kind we want, skip ahead to the next one
13387                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13388                                 ;
13389                         continue;
13390                 }
13391                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13392                 {
13393                         rsurface.lightmaptexture = NULL;
13394                         rsurface.deluxemaptexture = NULL;
13395                         rsurface.uselightmaptexture = false;
13396                         // simply scan ahead until we find a different texture or lightmap state
13397                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13398                                 ;
13399                 }
13400                 else
13401                 {
13402                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13403                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13404                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13405                         // simply scan ahead until we find a different texture or lightmap state
13406                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13407                                 ;
13408                 }
13409                 // render the range of surfaces
13410                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13411         }
13412 }
13413
13414 float locboxvertex3f[6*4*3] =
13415 {
13416         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13417         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13418         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13419         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13420         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13421         1,0,0, 0,0,0, 0,1,0, 1,1,0
13422 };
13423
13424 unsigned short locboxelements[6*2*3] =
13425 {
13426          0, 1, 2, 0, 2, 3,
13427          4, 5, 6, 4, 6, 7,
13428          8, 9,10, 8,10,11,
13429         12,13,14, 12,14,15,
13430         16,17,18, 16,18,19,
13431         20,21,22, 20,22,23
13432 };
13433
13434 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13435 {
13436         int i, j;
13437         cl_locnode_t *loc = (cl_locnode_t *)ent;
13438         vec3_t mins, size;
13439         float vertex3f[6*4*3];
13440         CHECKGLERROR
13441         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13442         GL_DepthMask(false);
13443         GL_DepthRange(0, 1);
13444         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13445         GL_DepthTest(true);
13446         GL_CullFace(GL_NONE);
13447         R_EntityMatrix(&identitymatrix);
13448
13449 //      R_Mesh_ResetTextureState();
13450
13451         i = surfacelist[0];
13452         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13453                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13454                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13455                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13456
13457         if (VectorCompare(loc->mins, loc->maxs))
13458         {
13459                 VectorSet(size, 2, 2, 2);
13460                 VectorMA(loc->mins, -0.5f, size, mins);
13461         }
13462         else
13463         {
13464                 VectorCopy(loc->mins, mins);
13465                 VectorSubtract(loc->maxs, loc->mins, size);
13466         }
13467
13468         for (i = 0;i < 6*4*3;)
13469                 for (j = 0;j < 3;j++, i++)
13470                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13471
13472         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13473         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13474         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13475 }
13476
13477 void R_DrawLocs(void)
13478 {
13479         int index;
13480         cl_locnode_t *loc, *nearestloc;
13481         vec3_t center;
13482         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13483         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13484         {
13485                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13486                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13487         }
13488 }
13489
13490 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13491 {
13492         if (decalsystem->decals)
13493                 Mem_Free(decalsystem->decals);
13494         memset(decalsystem, 0, sizeof(*decalsystem));
13495 }
13496
13497 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)
13498 {
13499         tridecal_t *decal;
13500         tridecal_t *decals;
13501         int i;
13502
13503         // expand or initialize the system
13504         if (decalsystem->maxdecals <= decalsystem->numdecals)
13505         {
13506                 decalsystem_t old = *decalsystem;
13507                 qboolean useshortelements;
13508                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13509                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13510                 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)));
13511                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13512                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13513                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13514                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13515                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13516                 if (decalsystem->numdecals)
13517                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13518                 if (old.decals)
13519                         Mem_Free(old.decals);
13520                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13521                         decalsystem->element3i[i] = i;
13522                 if (useshortelements)
13523                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13524                                 decalsystem->element3s[i] = i;
13525         }
13526
13527         // grab a decal and search for another free slot for the next one
13528         decals = decalsystem->decals;
13529         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13530         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13531                 ;
13532         decalsystem->freedecal = i;
13533         if (decalsystem->numdecals <= i)
13534                 decalsystem->numdecals = i + 1;
13535
13536         // initialize the decal
13537         decal->lived = 0;
13538         decal->triangleindex = triangleindex;
13539         decal->surfaceindex = surfaceindex;
13540         decal->decalsequence = decalsequence;
13541         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13542         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13543         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13544         decal->color4ub[0][3] = 255;
13545         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13546         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13547         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13548         decal->color4ub[1][3] = 255;
13549         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13550         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13551         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13552         decal->color4ub[2][3] = 255;
13553         decal->vertex3f[0][0] = v0[0];
13554         decal->vertex3f[0][1] = v0[1];
13555         decal->vertex3f[0][2] = v0[2];
13556         decal->vertex3f[1][0] = v1[0];
13557         decal->vertex3f[1][1] = v1[1];
13558         decal->vertex3f[1][2] = v1[2];
13559         decal->vertex3f[2][0] = v2[0];
13560         decal->vertex3f[2][1] = v2[1];
13561         decal->vertex3f[2][2] = v2[2];
13562         decal->texcoord2f[0][0] = t0[0];
13563         decal->texcoord2f[0][1] = t0[1];
13564         decal->texcoord2f[1][0] = t1[0];
13565         decal->texcoord2f[1][1] = t1[1];
13566         decal->texcoord2f[2][0] = t2[0];
13567         decal->texcoord2f[2][1] = t2[1];
13568 }
13569
13570 extern cvar_t cl_decals_bias;
13571 extern cvar_t cl_decals_models;
13572 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13573 // baseparms, parms, temps
13574 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)
13575 {
13576         int cornerindex;
13577         int index;
13578         float v[9][3];
13579         const float *vertex3f;
13580         int numpoints;
13581         float points[2][9][3];
13582         float temp[3];
13583         float tc[9][2];
13584         float f;
13585         float c[9][4];
13586         const int *e;
13587
13588         e = rsurface.modelelement3i + 3*triangleindex;
13589
13590         vertex3f = rsurface.modelvertex3f;
13591
13592         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13593         {
13594                 index = 3*e[cornerindex];
13595                 VectorCopy(vertex3f + index, v[cornerindex]);
13596         }
13597         // cull backfaces
13598         //TriangleNormal(v[0], v[1], v[2], normal);
13599         //if (DotProduct(normal, localnormal) < 0.0f)
13600         //      continue;
13601         // clip by each of the box planes formed from the projection matrix
13602         // if anything survives, we emit the decal
13603         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]);
13604         if (numpoints < 3)
13605                 return;
13606         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]);
13607         if (numpoints < 3)
13608                 return;
13609         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]);
13610         if (numpoints < 3)
13611                 return;
13612         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]);
13613         if (numpoints < 3)
13614                 return;
13615         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]);
13616         if (numpoints < 3)
13617                 return;
13618         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]);
13619         if (numpoints < 3)
13620                 return;
13621         // some part of the triangle survived, so we have to accept it...
13622         if (dynamic)
13623         {
13624                 // dynamic always uses the original triangle
13625                 numpoints = 3;
13626                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13627                 {
13628                         index = 3*e[cornerindex];
13629                         VectorCopy(vertex3f + index, v[cornerindex]);
13630                 }
13631         }
13632         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13633         {
13634                 // convert vertex positions to texcoords
13635                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13636                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13637                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13638                 // calculate distance fade from the projection origin
13639                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13640                 f = bound(0.0f, f, 1.0f);
13641                 c[cornerindex][0] = r * f;
13642                 c[cornerindex][1] = g * f;
13643                 c[cornerindex][2] = b * f;
13644                 c[cornerindex][3] = 1.0f;
13645                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13646         }
13647         if (dynamic)
13648                 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);
13649         else
13650                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13651                         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);
13652 }
13653 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)
13654 {
13655         matrix4x4_t projection;
13656         decalsystem_t *decalsystem;
13657         qboolean dynamic;
13658         dp_model_t *model;
13659         const msurface_t *surface;
13660         const msurface_t *surfaces;
13661         const int *surfacelist;
13662         const texture_t *texture;
13663         int numtriangles;
13664         int numsurfacelist;
13665         int surfacelistindex;
13666         int surfaceindex;
13667         int triangleindex;
13668         float localorigin[3];
13669         float localnormal[3];
13670         float localmins[3];
13671         float localmaxs[3];
13672         float localsize;
13673         //float normal[3];
13674         float planes[6][4];
13675         float angles[3];
13676         bih_t *bih;
13677         int bih_triangles_count;
13678         int bih_triangles[256];
13679         int bih_surfaces[256];
13680
13681         decalsystem = &ent->decalsystem;
13682         model = ent->model;
13683         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13684         {
13685                 R_DecalSystem_Reset(&ent->decalsystem);
13686                 return;
13687         }
13688
13689         if (!model->brush.data_leafs && !cl_decals_models.integer)
13690         {
13691                 if (decalsystem->model)
13692                         R_DecalSystem_Reset(decalsystem);
13693                 return;
13694         }
13695
13696         if (decalsystem->model != model)
13697                 R_DecalSystem_Reset(decalsystem);
13698         decalsystem->model = model;
13699
13700         RSurf_ActiveModelEntity(ent, false, false, false);
13701
13702         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13703         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13704         VectorNormalize(localnormal);
13705         localsize = worldsize*rsurface.inversematrixscale;
13706         localmins[0] = localorigin[0] - localsize;
13707         localmins[1] = localorigin[1] - localsize;
13708         localmins[2] = localorigin[2] - localsize;
13709         localmaxs[0] = localorigin[0] + localsize;
13710         localmaxs[1] = localorigin[1] + localsize;
13711         localmaxs[2] = localorigin[2] + localsize;
13712
13713         //VectorCopy(localnormal, planes[4]);
13714         //VectorVectors(planes[4], planes[2], planes[0]);
13715         AnglesFromVectors(angles, localnormal, NULL, false);
13716         AngleVectors(angles, planes[0], planes[2], planes[4]);
13717         VectorNegate(planes[0], planes[1]);
13718         VectorNegate(planes[2], planes[3]);
13719         VectorNegate(planes[4], planes[5]);
13720         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13721         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13722         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13723         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13724         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13725         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13726
13727 #if 1
13728 // works
13729 {
13730         matrix4x4_t forwardprojection;
13731         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13732         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13733 }
13734 #else
13735 // broken
13736 {
13737         float projectionvector[4][3];
13738         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13739         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13740         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13741         projectionvector[0][0] = planes[0][0] * ilocalsize;
13742         projectionvector[0][1] = planes[1][0] * ilocalsize;
13743         projectionvector[0][2] = planes[2][0] * ilocalsize;
13744         projectionvector[1][0] = planes[0][1] * ilocalsize;
13745         projectionvector[1][1] = planes[1][1] * ilocalsize;
13746         projectionvector[1][2] = planes[2][1] * ilocalsize;
13747         projectionvector[2][0] = planes[0][2] * ilocalsize;
13748         projectionvector[2][1] = planes[1][2] * ilocalsize;
13749         projectionvector[2][2] = planes[2][2] * ilocalsize;
13750         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13751         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13752         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13753         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13754 }
13755 #endif
13756
13757         dynamic = model->surfmesh.isanimated;
13758         numsurfacelist = model->nummodelsurfaces;
13759         surfacelist = model->sortedmodelsurfaces;
13760         surfaces = model->data_surfaces;
13761
13762         bih = NULL;
13763         bih_triangles_count = -1;
13764         if(!dynamic)
13765         {
13766                 if(model->render_bih.numleafs)
13767                         bih = &model->render_bih;
13768                 else if(model->collision_bih.numleafs)
13769                         bih = &model->collision_bih;
13770         }
13771         if(bih)
13772                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13773         if(bih_triangles_count == 0)
13774                 return;
13775         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13776                 return;
13777         if(bih_triangles_count > 0)
13778         {
13779                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13780                 {
13781                         surfaceindex = bih_surfaces[triangleindex];
13782                         surface = surfaces + surfaceindex;
13783                         texture = surface->texture;
13784                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13785                                 continue;
13786                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13787                                 continue;
13788                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13789                 }
13790         }
13791         else
13792         {
13793                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13794                 {
13795                         surfaceindex = surfacelist[surfacelistindex];
13796                         surface = surfaces + surfaceindex;
13797                         // check cull box first because it rejects more than any other check
13798                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13799                                 continue;
13800                         // skip transparent surfaces
13801                         texture = surface->texture;
13802                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13803                                 continue;
13804                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13805                                 continue;
13806                         numtriangles = surface->num_triangles;
13807                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13808                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13809                 }
13810         }
13811 }
13812
13813 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13814 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)
13815 {
13816         int renderentityindex;
13817         float worldmins[3];
13818         float worldmaxs[3];
13819         entity_render_t *ent;
13820
13821         if (!cl_decals_newsystem.integer)
13822                 return;
13823
13824         worldmins[0] = worldorigin[0] - worldsize;
13825         worldmins[1] = worldorigin[1] - worldsize;
13826         worldmins[2] = worldorigin[2] - worldsize;
13827         worldmaxs[0] = worldorigin[0] + worldsize;
13828         worldmaxs[1] = worldorigin[1] + worldsize;
13829         worldmaxs[2] = worldorigin[2] + worldsize;
13830
13831         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13832
13833         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13834         {
13835                 ent = r_refdef.scene.entities[renderentityindex];
13836                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13837                         continue;
13838
13839                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13840         }
13841 }
13842
13843 typedef struct r_decalsystem_splatqueue_s
13844 {
13845         vec3_t worldorigin;
13846         vec3_t worldnormal;
13847         float color[4];
13848         float tcrange[4];
13849         float worldsize;
13850         int decalsequence;
13851 }
13852 r_decalsystem_splatqueue_t;
13853
13854 int r_decalsystem_numqueued = 0;
13855 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13856
13857 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)
13858 {
13859         r_decalsystem_splatqueue_t *queue;
13860
13861         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13862                 return;
13863
13864         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13865         VectorCopy(worldorigin, queue->worldorigin);
13866         VectorCopy(worldnormal, queue->worldnormal);
13867         Vector4Set(queue->color, r, g, b, a);
13868         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13869         queue->worldsize = worldsize;
13870         queue->decalsequence = cl.decalsequence++;
13871 }
13872
13873 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13874 {
13875         int i;
13876         r_decalsystem_splatqueue_t *queue;
13877
13878         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13879                 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);
13880         r_decalsystem_numqueued = 0;
13881 }
13882
13883 extern cvar_t cl_decals_max;
13884 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13885 {
13886         int i;
13887         decalsystem_t *decalsystem = &ent->decalsystem;
13888         int numdecals;
13889         int killsequence;
13890         tridecal_t *decal;
13891         float frametime;
13892         float lifetime;
13893
13894         if (!decalsystem->numdecals)
13895                 return;
13896
13897         if (r_showsurfaces.integer)
13898                 return;
13899
13900         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13901         {
13902                 R_DecalSystem_Reset(decalsystem);
13903                 return;
13904         }
13905
13906         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13907         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13908
13909         if (decalsystem->lastupdatetime)
13910                 frametime = (cl.time - decalsystem->lastupdatetime);
13911         else
13912                 frametime = 0;
13913         decalsystem->lastupdatetime = cl.time;
13914         decal = decalsystem->decals;
13915         numdecals = decalsystem->numdecals;
13916
13917         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13918         {
13919                 if (decal->color4ub[0][3])
13920                 {
13921                         decal->lived += frametime;
13922                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13923                         {
13924                                 memset(decal, 0, sizeof(*decal));
13925                                 if (decalsystem->freedecal > i)
13926                                         decalsystem->freedecal = i;
13927                         }
13928                 }
13929         }
13930         decal = decalsystem->decals;
13931         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13932                 numdecals--;
13933
13934         // collapse the array by shuffling the tail decals into the gaps
13935         for (;;)
13936         {
13937                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13938                         decalsystem->freedecal++;
13939                 if (decalsystem->freedecal == numdecals)
13940                         break;
13941                 decal[decalsystem->freedecal] = decal[--numdecals];
13942         }
13943
13944         decalsystem->numdecals = numdecals;
13945
13946         if (numdecals <= 0)
13947         {
13948                 // if there are no decals left, reset decalsystem
13949                 R_DecalSystem_Reset(decalsystem);
13950         }
13951 }
13952
13953 extern skinframe_t *decalskinframe;
13954 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13955 {
13956         int i;
13957         decalsystem_t *decalsystem = &ent->decalsystem;
13958         int numdecals;
13959         tridecal_t *decal;
13960         float faderate;
13961         float alpha;
13962         float *v3f;
13963         float *c4f;
13964         float *t2f;
13965         const int *e;
13966         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13967         int numtris = 0;
13968
13969         numdecals = decalsystem->numdecals;
13970         if (!numdecals)
13971                 return;
13972
13973         if (r_showsurfaces.integer)
13974                 return;
13975
13976         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13977         {
13978                 R_DecalSystem_Reset(decalsystem);
13979                 return;
13980         }
13981
13982         // if the model is static it doesn't matter what value we give for
13983         // wantnormals and wanttangents, so this logic uses only rules applicable
13984         // to a model, knowing that they are meaningless otherwise
13985         if (ent == r_refdef.scene.worldentity)
13986                 RSurf_ActiveWorldEntity();
13987         else
13988                 RSurf_ActiveModelEntity(ent, false, false, false);
13989
13990         decalsystem->lastupdatetime = cl.time;
13991         decal = decalsystem->decals;
13992
13993         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13994
13995         // update vertex positions for animated models
13996         v3f = decalsystem->vertex3f;
13997         c4f = decalsystem->color4f;
13998         t2f = decalsystem->texcoord2f;
13999         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14000         {
14001                 if (!decal->color4ub[0][3])
14002                         continue;
14003
14004                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
14005                         continue;
14006
14007                 // update color values for fading decals
14008                 if (decal->lived >= cl_decals_time.value)
14009                 {
14010                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
14011                         alpha *= (1.0f/255.0f);
14012                 }
14013                 else
14014                         alpha = 1.0f/255.0f;
14015
14016                 c4f[ 0] = decal->color4ub[0][0] * alpha;
14017                 c4f[ 1] = decal->color4ub[0][1] * alpha;
14018                 c4f[ 2] = decal->color4ub[0][2] * alpha;
14019                 c4f[ 3] = 1;
14020                 c4f[ 4] = decal->color4ub[1][0] * alpha;
14021                 c4f[ 5] = decal->color4ub[1][1] * alpha;
14022                 c4f[ 6] = decal->color4ub[1][2] * alpha;
14023                 c4f[ 7] = 1;
14024                 c4f[ 8] = decal->color4ub[2][0] * alpha;
14025                 c4f[ 9] = decal->color4ub[2][1] * alpha;
14026                 c4f[10] = decal->color4ub[2][2] * alpha;
14027                 c4f[11] = 1;
14028
14029                 t2f[0] = decal->texcoord2f[0][0];
14030                 t2f[1] = decal->texcoord2f[0][1];
14031                 t2f[2] = decal->texcoord2f[1][0];
14032                 t2f[3] = decal->texcoord2f[1][1];
14033                 t2f[4] = decal->texcoord2f[2][0];
14034                 t2f[5] = decal->texcoord2f[2][1];
14035
14036                 // update vertex positions for animated models
14037                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
14038                 {
14039                         e = rsurface.modelelement3i + 3*decal->triangleindex;
14040                         VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
14041                         VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
14042                         VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
14043                 }
14044                 else
14045                 {
14046                         VectorCopy(decal->vertex3f[0], v3f);
14047                         VectorCopy(decal->vertex3f[1], v3f + 3);
14048                         VectorCopy(decal->vertex3f[2], v3f + 6);
14049                 }
14050
14051                 if (r_refdef.fogenabled)
14052                 {
14053                         alpha = RSurf_FogVertex(v3f);
14054                         VectorScale(c4f, alpha, c4f);
14055                         alpha = RSurf_FogVertex(v3f + 3);
14056                         VectorScale(c4f + 4, alpha, c4f + 4);
14057                         alpha = RSurf_FogVertex(v3f + 6);
14058                         VectorScale(c4f + 8, alpha, c4f + 8);
14059                 }
14060
14061                 v3f += 9;
14062                 c4f += 12;
14063                 t2f += 6;
14064                 numtris++;
14065         }
14066
14067         if (numtris > 0)
14068         {
14069                 r_refdef.stats.drawndecals += numtris;
14070
14071                 // now render the decals all at once
14072                 // (this assumes they all use one particle font texture!)
14073                 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);
14074 //              R_Mesh_ResetTextureState();
14075                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
14076                 GL_DepthMask(false);
14077                 GL_DepthRange(0, 1);
14078                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
14079                 GL_DepthTest(true);
14080                 GL_CullFace(GL_NONE);
14081                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
14082                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
14083                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
14084         }
14085 }
14086
14087 static void R_DrawModelDecals(void)
14088 {
14089         int i, numdecals;
14090
14091         // fade faster when there are too many decals
14092         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14093         for (i = 0;i < r_refdef.scene.numentities;i++)
14094                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14095
14096         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
14097         for (i = 0;i < r_refdef.scene.numentities;i++)
14098                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14099                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14100
14101         R_DecalSystem_ApplySplatEntitiesQueue();
14102
14103         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14104         for (i = 0;i < r_refdef.scene.numentities;i++)
14105                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14106
14107         r_refdef.stats.totaldecals += numdecals;
14108
14109         if (r_showsurfaces.integer)
14110                 return;
14111
14112         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14113
14114         for (i = 0;i < r_refdef.scene.numentities;i++)
14115         {
14116                 if (!r_refdef.viewcache.entityvisible[i])
14117                         continue;
14118                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14119                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14120         }
14121 }
14122
14123 extern cvar_t mod_collision_bih;
14124 void R_DrawDebugModel(void)
14125 {
14126         entity_render_t *ent = rsurface.entity;
14127         int i, j, k, l, flagsmask;
14128         const msurface_t *surface;
14129         dp_model_t *model = ent->model;
14130         vec3_t v;
14131
14132         switch(vid.renderpath)
14133         {
14134         case RENDERPATH_GL11:
14135         case RENDERPATH_GL13:
14136         case RENDERPATH_GL20:
14137         case RENDERPATH_CGGL:
14138                 break;
14139         case RENDERPATH_D3D9:
14140                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14141                 return;
14142         case RENDERPATH_D3D10:
14143                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14144                 return;
14145         case RENDERPATH_D3D11:
14146                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14147                 return;
14148         }
14149
14150         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14151
14152 //      R_Mesh_ResetTextureState();
14153         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14154         GL_DepthRange(0, 1);
14155         GL_DepthTest(!r_showdisabledepthtest.integer);
14156         GL_DepthMask(false);
14157         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14158
14159         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14160         {
14161                 int triangleindex;
14162                 int bihleafindex;
14163                 qboolean cullbox = ent == r_refdef.scene.worldentity;
14164                 const q3mbrush_t *brush;
14165                 const bih_t *bih = &model->collision_bih;
14166                 const bih_leaf_t *bihleaf;
14167                 float vertex3f[3][3];
14168                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14169                 cullbox = false;
14170                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14171                 {
14172                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14173                                 continue;
14174                         switch (bihleaf->type)
14175                         {
14176                         case BIH_BRUSH:
14177                                 brush = model->brush.data_brushes + bihleaf->itemindex;
14178                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
14179                                 {
14180                                         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);
14181                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14182                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14183                                 }
14184                                 break;
14185                         case BIH_COLLISIONTRIANGLE:
14186                                 triangleindex = bihleaf->itemindex;
14187                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14188                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14189                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14190                                 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);
14191                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14192                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14193                                 break;
14194                         case BIH_RENDERTRIANGLE:
14195                                 triangleindex = bihleaf->itemindex;
14196                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14197                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14198                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14199                                 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);
14200                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14201                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14202                                 break;
14203                         }
14204                 }
14205         }
14206
14207         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14208
14209         if (r_showtris.integer || r_shownormals.integer)
14210         {
14211                 if (r_showdisabledepthtest.integer)
14212                 {
14213                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14214                         GL_DepthMask(false);
14215                 }
14216                 else
14217                 {
14218                         GL_BlendFunc(GL_ONE, GL_ZERO);
14219                         GL_DepthMask(true);
14220                 }
14221                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14222                 {
14223                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14224                                 continue;
14225                         rsurface.texture = R_GetCurrentTexture(surface->texture);
14226                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14227                         {
14228                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14229                                 if (r_showtris.value > 0)
14230                                 {
14231                                         if (!rsurface.texture->currentlayers->depthmask)
14232                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14233                                         else if (ent == r_refdef.scene.worldentity)
14234                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14235                                         else
14236                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14237                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14238                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14239                                         RSurf_DrawBatch();
14240                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14241                                         CHECKGLERROR
14242                                 }
14243                                 if (r_shownormals.value < 0)
14244                                 {
14245                                         qglBegin(GL_LINES);
14246                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14247                                         {
14248                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14249                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14250                                                 qglVertex3f(v[0], v[1], v[2]);
14251                                                 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14252                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14253                                                 qglVertex3f(v[0], v[1], v[2]);
14254                                         }
14255                                         qglEnd();
14256                                         CHECKGLERROR
14257                                 }
14258                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14259                                 {
14260                                         qglBegin(GL_LINES);
14261                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14262                                         {
14263                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14264                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14265                                                 qglVertex3f(v[0], v[1], v[2]);
14266                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14267                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14268                                                 qglVertex3f(v[0], v[1], v[2]);
14269                                         }
14270                                         qglEnd();
14271                                         CHECKGLERROR
14272                                         qglBegin(GL_LINES);
14273                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14274                                         {
14275                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14276                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14277                                                 qglVertex3f(v[0], v[1], v[2]);
14278                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14279                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14280                                                 qglVertex3f(v[0], v[1], v[2]);
14281                                         }
14282                                         qglEnd();
14283                                         CHECKGLERROR
14284                                         qglBegin(GL_LINES);
14285                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;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, 1, 1, 1);
14292                                                 qglVertex3f(v[0], v[1], v[2]);
14293                                         }
14294                                         qglEnd();
14295                                         CHECKGLERROR
14296                                 }
14297                         }
14298                 }
14299                 rsurface.texture = NULL;
14300         }
14301 }
14302
14303 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14304 int r_maxsurfacelist = 0;
14305 const msurface_t **r_surfacelist = NULL;
14306 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14307 {
14308         int i, j, endj, flagsmask;
14309         dp_model_t *model = r_refdef.scene.worldmodel;
14310         msurface_t *surfaces;
14311         unsigned char *update;
14312         int numsurfacelist = 0;
14313         if (model == NULL)
14314                 return;
14315
14316         if (r_maxsurfacelist < model->num_surfaces)
14317         {
14318                 r_maxsurfacelist = model->num_surfaces;
14319                 if (r_surfacelist)
14320                         Mem_Free((msurface_t**)r_surfacelist);
14321                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14322         }
14323
14324         RSurf_ActiveWorldEntity();
14325
14326         surfaces = model->data_surfaces;
14327         update = model->brushq1.lightmapupdateflags;
14328
14329         // update light styles on this submodel
14330         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14331         {
14332                 model_brush_lightstyleinfo_t *style;
14333                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14334                 {
14335                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14336                         {
14337                                 int *list = style->surfacelist;
14338                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14339                                 for (j = 0;j < style->numsurfaces;j++)
14340                                         update[list[j]] = true;
14341                         }
14342                 }
14343         }
14344
14345         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14346
14347         if (debug)
14348         {
14349                 R_DrawDebugModel();
14350                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14351                 return;
14352         }
14353
14354         rsurface.lightmaptexture = NULL;
14355         rsurface.deluxemaptexture = NULL;
14356         rsurface.uselightmaptexture = false;
14357         rsurface.texture = NULL;
14358         rsurface.rtlight = NULL;
14359         numsurfacelist = 0;
14360         // add visible surfaces to draw list
14361         for (i = 0;i < model->nummodelsurfaces;i++)
14362         {
14363                 j = model->sortedmodelsurfaces[i];
14364                 if (r_refdef.viewcache.world_surfacevisible[j])
14365                         r_surfacelist[numsurfacelist++] = surfaces + j;
14366         }
14367         // update lightmaps if needed
14368         if (model->brushq1.firstrender)
14369         {
14370                 model->brushq1.firstrender = false;
14371                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14372                         if (update[j])
14373                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14374         }
14375         else if (update)
14376         {
14377                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14378                         if (r_refdef.viewcache.world_surfacevisible[j])
14379                                 if (update[j])
14380                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14381         }
14382         // don't do anything if there were no surfaces
14383         if (!numsurfacelist)
14384         {
14385                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14386                 return;
14387         }
14388         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14389         GL_AlphaTest(false);
14390
14391         // add to stats if desired
14392         if (r_speeds.integer && !skysurfaces && !depthonly)
14393         {
14394                 r_refdef.stats.world_surfaces += numsurfacelist;
14395                 for (j = 0;j < numsurfacelist;j++)
14396                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14397         }
14398
14399         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14400 }
14401
14402 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14403 {
14404         int i, j, endj, flagsmask;
14405         dp_model_t *model = ent->model;
14406         msurface_t *surfaces;
14407         unsigned char *update;
14408         int numsurfacelist = 0;
14409         if (model == NULL)
14410                 return;
14411
14412         if (r_maxsurfacelist < model->num_surfaces)
14413         {
14414                 r_maxsurfacelist = model->num_surfaces;
14415                 if (r_surfacelist)
14416                         Mem_Free((msurface_t **)r_surfacelist);
14417                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14418         }
14419
14420         // if the model is static it doesn't matter what value we give for
14421         // wantnormals and wanttangents, so this logic uses only rules applicable
14422         // to a model, knowing that they are meaningless otherwise
14423         if (ent == r_refdef.scene.worldentity)
14424                 RSurf_ActiveWorldEntity();
14425         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14426                 RSurf_ActiveModelEntity(ent, false, false, false);
14427         else if (prepass)
14428                 RSurf_ActiveModelEntity(ent, true, true, true);
14429         else if (depthonly)
14430         {
14431                 switch (vid.renderpath)
14432                 {
14433                 case RENDERPATH_GL20:
14434                 case RENDERPATH_CGGL:
14435                 case RENDERPATH_D3D9:
14436                 case RENDERPATH_D3D10:
14437                 case RENDERPATH_D3D11:
14438                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14439                         break;
14440                 case RENDERPATH_GL13:
14441                 case RENDERPATH_GL11:
14442                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14443                         break;
14444                 }
14445         }
14446         else
14447         {
14448                 switch (vid.renderpath)
14449                 {
14450                 case RENDERPATH_GL20:
14451                 case RENDERPATH_CGGL:
14452                 case RENDERPATH_D3D9:
14453                 case RENDERPATH_D3D10:
14454                 case RENDERPATH_D3D11:
14455                         RSurf_ActiveModelEntity(ent, true, true, false);
14456                         break;
14457                 case RENDERPATH_GL13:
14458                 case RENDERPATH_GL11:
14459                         RSurf_ActiveModelEntity(ent, true, false, false);
14460                         break;
14461                 }
14462         }
14463
14464         surfaces = model->data_surfaces;
14465         update = model->brushq1.lightmapupdateflags;
14466
14467         // update light styles
14468         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14469         {
14470                 model_brush_lightstyleinfo_t *style;
14471                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14472                 {
14473                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14474                         {
14475                                 int *list = style->surfacelist;
14476                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14477                                 for (j = 0;j < style->numsurfaces;j++)
14478                                         update[list[j]] = true;
14479                         }
14480                 }
14481         }
14482
14483         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14484
14485         if (debug)
14486         {
14487                 R_DrawDebugModel();
14488                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14489                 return;
14490         }
14491
14492         rsurface.lightmaptexture = NULL;
14493         rsurface.deluxemaptexture = NULL;
14494         rsurface.uselightmaptexture = false;
14495         rsurface.texture = NULL;
14496         rsurface.rtlight = NULL;
14497         numsurfacelist = 0;
14498         // add visible surfaces to draw list
14499         for (i = 0;i < model->nummodelsurfaces;i++)
14500                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14501         // don't do anything if there were no surfaces
14502         if (!numsurfacelist)
14503         {
14504                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14505                 return;
14506         }
14507         // update lightmaps if needed
14508         if (update)
14509         {
14510                 int updated = 0;
14511                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14512                 {
14513                         if (update[j])
14514                         {
14515                                 updated++;
14516                                 R_BuildLightMap(ent, surfaces + j);
14517                         }
14518                 }
14519         }
14520         if (update)
14521                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14522                         if (update[j])
14523                                 R_BuildLightMap(ent, surfaces + j);
14524         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14525         GL_AlphaTest(false);
14526
14527         // add to stats if desired
14528         if (r_speeds.integer && !skysurfaces && !depthonly)
14529         {
14530                 r_refdef.stats.entities_surfaces += numsurfacelist;
14531                 for (j = 0;j < numsurfacelist;j++)
14532                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14533         }
14534
14535         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14536 }
14537
14538 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14539 {
14540         static texture_t texture;
14541         static msurface_t surface;
14542         const msurface_t *surfacelist = &surface;
14543
14544         // fake enough texture and surface state to render this geometry
14545
14546         texture.update_lastrenderframe = -1; // regenerate this texture
14547         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14548         texture.currentskinframe = skinframe;
14549         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14550         texture.offsetmapping = OFFSETMAPPING_OFF;
14551         texture.offsetscale = 1;
14552         texture.specularscalemod = 1;
14553         texture.specularpowermod = 1;
14554
14555         surface.texture = &texture;
14556         surface.num_triangles = numtriangles;
14557         surface.num_firsttriangle = firsttriangle;
14558         surface.num_vertices = numvertices;
14559         surface.num_firstvertex = firstvertex;
14560
14561         // now render it
14562         rsurface.texture = R_GetCurrentTexture(surface.texture);
14563         rsurface.lightmaptexture = NULL;
14564         rsurface.deluxemaptexture = NULL;
14565         rsurface.uselightmaptexture = false;
14566         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14567 }
14568
14569 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)
14570 {
14571         static msurface_t surface;
14572         const msurface_t *surfacelist = &surface;
14573
14574         // fake enough texture and surface state to render this geometry
14575         surface.texture = texture;
14576         surface.num_triangles = numtriangles;
14577         surface.num_firsttriangle = firsttriangle;
14578         surface.num_vertices = numvertices;
14579         surface.num_firstvertex = firstvertex;
14580
14581         // now render it
14582         rsurface.texture = R_GetCurrentTexture(surface.texture);
14583         rsurface.lightmaptexture = NULL;
14584         rsurface.deluxemaptexture = NULL;
14585         rsurface.uselightmaptexture = false;
14586         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14587 }