]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
fix wrong-texture rendering in stonekeep where a 0-triangles patch
[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 + float2(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);\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 is multiplied by SHADERPERMUTATION_MODEBASE
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, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
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"},
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_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3477         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3478         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3479         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3480         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3481         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3482         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3483         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3484         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3485 };
3486 #endif
3487
3488 struct r_glsl_permutation_s;
3489 typedef struct r_glsl_permutation_s
3490 {
3491         /// hash lookup data
3492         struct r_glsl_permutation_s *hashnext;
3493         unsigned int mode;
3494         unsigned int permutation;
3495
3496         /// indicates if we have tried compiling this permutation already
3497         qboolean compiled;
3498         /// 0 if compilation failed
3499         int program;
3500         /// locations of detected uniforms in program object, or -1 if not found
3501         int loc_Texture_First;
3502         int loc_Texture_Second;
3503         int loc_Texture_GammaRamps;
3504         int loc_Texture_Normal;
3505         int loc_Texture_Color;
3506         int loc_Texture_Gloss;
3507         int loc_Texture_Glow;
3508         int loc_Texture_SecondaryNormal;
3509         int loc_Texture_SecondaryColor;
3510         int loc_Texture_SecondaryGloss;
3511         int loc_Texture_SecondaryGlow;
3512         int loc_Texture_Pants;
3513         int loc_Texture_Shirt;
3514         int loc_Texture_FogHeightTexture;
3515         int loc_Texture_FogMask;
3516         int loc_Texture_Lightmap;
3517         int loc_Texture_Deluxemap;
3518         int loc_Texture_Attenuation;
3519         int loc_Texture_Cube;
3520         int loc_Texture_Refraction;
3521         int loc_Texture_Reflection;
3522         int loc_Texture_ShadowMap2D;
3523         int loc_Texture_CubeProjection;
3524         int loc_Texture_ScreenDepth;
3525         int loc_Texture_ScreenNormalMap;
3526         int loc_Texture_ScreenDiffuse;
3527         int loc_Texture_ScreenSpecular;
3528         int loc_Texture_ReflectMask;
3529         int loc_Texture_ReflectCube;
3530         int loc_Alpha;
3531         int loc_BloomBlur_Parameters;
3532         int loc_ClientTime;
3533         int loc_Color_Ambient;
3534         int loc_Color_Diffuse;
3535         int loc_Color_Specular;
3536         int loc_Color_Glow;
3537         int loc_Color_Pants;
3538         int loc_Color_Shirt;
3539         int loc_DeferredColor_Ambient;
3540         int loc_DeferredColor_Diffuse;
3541         int loc_DeferredColor_Specular;
3542         int loc_DeferredMod_Diffuse;
3543         int loc_DeferredMod_Specular;
3544         int loc_DistortScaleRefractReflect;
3545         int loc_EyePosition;
3546         int loc_FogColor;
3547         int loc_FogHeightFade;
3548         int loc_FogPlane;
3549         int loc_FogPlaneViewDist;
3550         int loc_FogRangeRecip;
3551         int loc_LightColor;
3552         int loc_LightDir;
3553         int loc_LightPosition;
3554         int loc_OffsetMapping_Scale;
3555         int loc_PixelSize;
3556         int loc_ReflectColor;
3557         int loc_ReflectFactor;
3558         int loc_ReflectOffset;
3559         int loc_RefractColor;
3560         int loc_Saturation;
3561         int loc_ScreenCenterRefractReflect;
3562         int loc_ScreenScaleRefractReflect;
3563         int loc_ScreenToDepth;
3564         int loc_ShadowMap_Parameters;
3565         int loc_ShadowMap_TextureScale;
3566         int loc_SpecularPower;
3567         int loc_UserVec1;
3568         int loc_UserVec2;
3569         int loc_UserVec3;
3570         int loc_UserVec4;
3571         int loc_ViewTintColor;
3572         int loc_ViewToLight;
3573         int loc_ModelToLight;
3574         int loc_TexMatrix;
3575         int loc_BackgroundTexMatrix;
3576         int loc_ModelViewProjectionMatrix;
3577         int loc_ModelViewMatrix;
3578         int loc_PixelToScreenTexCoord;
3579         int loc_ModelToReflectCube;
3580         int loc_ShadowMapMatrix;
3581         int loc_BloomColorSubtract;
3582         int loc_NormalmapScrollBlend;
3583 }
3584 r_glsl_permutation_t;
3585
3586 #define SHADERPERMUTATION_HASHSIZE 256
3587
3588
3589 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3590 // these can NOT degrade! only use for simple stuff
3591 enum
3592 {
3593         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3594         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3595         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3596         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3597         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3598         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
3599 };
3600 #define SHADERSTATICPARMS_COUNT 6
3601
3602 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3603 static int shaderstaticparms_count = 0;
3604
3605 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3606 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3607 qboolean R_CompileShader_CheckStaticParms(void)
3608 {
3609         static int r_compileshader_staticparms_save[1];
3610         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3611         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3612
3613         // detect all
3614         if (r_glsl_saturation_redcompensate.integer)
3615                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3616         if (r_shadow_glossexact.integer)
3617                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3618         if (r_glsl_postprocess.integer)
3619         {
3620                 if (r_glsl_postprocess_uservec1_enable.integer)
3621                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3622                 if (r_glsl_postprocess_uservec2_enable.integer)
3623                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3624                 if (r_glsl_postprocess_uservec3_enable.integer)
3625                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3626                 if (r_glsl_postprocess_uservec4_enable.integer)
3627                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3628         }
3629         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3630 }
3631
3632 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3633         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3634                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3635         else \
3636                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3637 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3638 {
3639         shaderstaticparms_count = 0;
3640
3641         // emit all
3642         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3643         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3644         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3645         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3646         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3647         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3648 }
3649
3650 /// information about each possible shader permutation
3651 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3652 /// currently selected permutation
3653 r_glsl_permutation_t *r_glsl_permutation;
3654 /// storage for permutations linked in the hash table
3655 memexpandablearray_t r_glsl_permutationarray;
3656
3657 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3658 {
3659         //unsigned int hashdepth = 0;
3660         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3661         r_glsl_permutation_t *p;
3662         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3663         {
3664                 if (p->mode == mode && p->permutation == permutation)
3665                 {
3666                         //if (hashdepth > 10)
3667                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3668                         return p;
3669                 }
3670                 //hashdepth++;
3671         }
3672         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3673         p->mode = mode;
3674         p->permutation = permutation;
3675         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3676         r_glsl_permutationhash[mode][hashindex] = p;
3677         //if (hashdepth > 10)
3678         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3679         return p;
3680 }
3681
3682 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3683 {
3684         char *shaderstring;
3685         if (!filename || !filename[0])
3686                 return NULL;
3687         if (!strcmp(filename, "glsl/default.glsl"))
3688         {
3689                 if (!glslshaderstring)
3690                 {
3691                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3692                         if (glslshaderstring)
3693                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3694                         else
3695                                 glslshaderstring = (char *)builtinshaderstring;
3696                 }
3697                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3698                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3699                 return shaderstring;
3700         }
3701         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3702         if (shaderstring)
3703         {
3704                 if (printfromdisknotice)
3705                         Con_DPrintf("from disk %s... ", filename);
3706                 return shaderstring;
3707         }
3708         return shaderstring;
3709 }
3710
3711 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3712 {
3713         int i;
3714         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3715         char *vertexstring, *geometrystring, *fragmentstring;
3716         char permutationname[256];
3717         int vertstrings_count = 0;
3718         int geomstrings_count = 0;
3719         int fragstrings_count = 0;
3720         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3721         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3722         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3723
3724         if (p->compiled)
3725                 return;
3726         p->compiled = true;
3727         p->program = 0;
3728
3729         permutationname[0] = 0;
3730         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3731         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3732         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3733
3734         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3735
3736         // the first pretext is which type of shader to compile as
3737         // (later these will all be bound together as a program object)
3738         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3739         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3740         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3741
3742         // the second pretext is the mode (for example a light source)
3743         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3744         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3745         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3746         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3747
3748         // now add all the permutation pretexts
3749         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3750         {
3751                 if (permutation & (1<<i))
3752                 {
3753                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3754                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3755                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3756                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3757                 }
3758                 else
3759                 {
3760                         // keep line numbers correct
3761                         vertstrings_list[vertstrings_count++] = "\n";
3762                         geomstrings_list[geomstrings_count++] = "\n";
3763                         fragstrings_list[fragstrings_count++] = "\n";
3764                 }
3765         }
3766
3767         // add static parms
3768         R_CompileShader_AddStaticParms(mode, permutation);
3769         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3770         vertstrings_count += shaderstaticparms_count;
3771         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3772         geomstrings_count += shaderstaticparms_count;
3773         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3774         fragstrings_count += shaderstaticparms_count;
3775
3776         // now append the shader text itself
3777         vertstrings_list[vertstrings_count++] = vertexstring;
3778         geomstrings_list[geomstrings_count++] = geometrystring;
3779         fragstrings_list[fragstrings_count++] = fragmentstring;
3780
3781         // if any sources were NULL, clear the respective list
3782         if (!vertexstring)
3783                 vertstrings_count = 0;
3784         if (!geometrystring)
3785                 geomstrings_count = 0;
3786         if (!fragmentstring)
3787                 fragstrings_count = 0;
3788
3789         // compile the shader program
3790         if (vertstrings_count + geomstrings_count + fragstrings_count)
3791                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3792         if (p->program)
3793         {
3794                 CHECKGLERROR
3795                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3796                 // look up all the uniform variable names we care about, so we don't
3797                 // have to look them up every time we set them
3798
3799                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3800                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3801                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3802                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3803                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3804                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3805                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3806                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3807                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3808                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3809                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3810                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3811                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3812                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3813                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3814                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3815                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3816                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3817                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3818                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3819                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3820                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3821                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3822                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3823                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3824                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3825                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3826                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3827                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3828                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3829                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3830                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3831                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3832                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3833                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3834                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3835                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3836                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3837                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3838                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3839                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3840                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3841                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3842                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3843                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3844                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3845                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3846                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3847                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3848                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3849                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3850                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3851                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3852                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3853                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3854                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3855                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3856                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3857                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3858                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3859                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3860                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3861                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3862                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3863                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3864                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3865                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3866                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3867                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3868                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3869                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3870                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3871                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3872                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3873                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3874                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3875                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3876                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3877                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3878                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3879                 p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3880                 p->loc_NormalmapScrollBlend       = qglGetUniformLocationARB(p->program, "NormalmapScrollBlend");
3881                 // initialize the samplers to refer to the texture units we use
3882                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3883                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3884                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3885                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3886                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3887                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3888                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3889                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3890                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3891                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3892                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3893                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3894                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3895                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3896                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3897                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3898                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3899                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3900                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3901                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3902                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3903                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3904                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3905                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3906                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3907                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3908                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3909                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3910                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3911                 CHECKGLERROR
3912                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3913         }
3914         else
3915                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3916
3917         // free the strings
3918         if (vertexstring)
3919                 Mem_Free(vertexstring);
3920         if (geometrystring)
3921                 Mem_Free(geometrystring);
3922         if (fragmentstring)
3923                 Mem_Free(fragmentstring);
3924 }
3925
3926 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3927 {
3928         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3929         if (r_glsl_permutation != perm)
3930         {
3931                 r_glsl_permutation = perm;
3932                 if (!r_glsl_permutation->program)
3933                 {
3934                         if (!r_glsl_permutation->compiled)
3935                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3936                         if (!r_glsl_permutation->program)
3937                         {
3938                                 // remove features until we find a valid permutation
3939                                 int i;
3940                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3941                                 {
3942                                         // reduce i more quickly whenever it would not remove any bits
3943                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3944                                         if (!(permutation & j))
3945                                                 continue;
3946                                         permutation -= j;
3947                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3948                                         if (!r_glsl_permutation->compiled)
3949                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3950                                         if (r_glsl_permutation->program)
3951                                                 break;
3952                                 }
3953                                 if (i >= SHADERPERMUTATION_COUNT)
3954                                 {
3955                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3956                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3957                                         qglUseProgramObjectARB(0);CHECKGLERROR
3958                                         return; // no bit left to clear, entire mode is broken
3959                                 }
3960                         }
3961                 }
3962                 CHECKGLERROR
3963                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3964         }
3965         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3966         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3967         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3968 }
3969
3970 #ifdef SUPPORTCG
3971 #include <Cg/cgGL.h>
3972 struct r_cg_permutation_s;
3973 typedef struct r_cg_permutation_s
3974 {
3975         /// hash lookup data
3976         struct r_cg_permutation_s *hashnext;
3977         unsigned int mode;
3978         unsigned int permutation;
3979
3980         /// indicates if we have tried compiling this permutation already
3981         qboolean compiled;
3982         /// 0 if compilation failed
3983         CGprogram vprogram;
3984         CGprogram fprogram;
3985         /// locations of detected parameters in programs, or NULL if not found
3986         CGparameter vp_EyePosition;
3987         CGparameter vp_FogPlane;
3988         CGparameter vp_LightDir;
3989         CGparameter vp_LightPosition;
3990         CGparameter vp_ModelToLight;
3991         CGparameter vp_TexMatrix;
3992         CGparameter vp_BackgroundTexMatrix;
3993         CGparameter vp_ModelViewProjectionMatrix;
3994         CGparameter vp_ModelViewMatrix;
3995         CGparameter vp_ShadowMapMatrix;
3996
3997         CGparameter fp_Texture_First;
3998         CGparameter fp_Texture_Second;
3999         CGparameter fp_Texture_GammaRamps;
4000         CGparameter fp_Texture_Normal;
4001         CGparameter fp_Texture_Color;
4002         CGparameter fp_Texture_Gloss;
4003         CGparameter fp_Texture_Glow;
4004         CGparameter fp_Texture_SecondaryNormal;
4005         CGparameter fp_Texture_SecondaryColor;
4006         CGparameter fp_Texture_SecondaryGloss;
4007         CGparameter fp_Texture_SecondaryGlow;
4008         CGparameter fp_Texture_Pants;
4009         CGparameter fp_Texture_Shirt;
4010         CGparameter fp_Texture_FogHeightTexture;
4011         CGparameter fp_Texture_FogMask;
4012         CGparameter fp_Texture_Lightmap;
4013         CGparameter fp_Texture_Deluxemap;
4014         CGparameter fp_Texture_Attenuation;
4015         CGparameter fp_Texture_Cube;
4016         CGparameter fp_Texture_Refraction;
4017         CGparameter fp_Texture_Reflection;
4018         CGparameter fp_Texture_ShadowMap2D;
4019         CGparameter fp_Texture_CubeProjection;
4020         CGparameter fp_Texture_ScreenDepth;
4021         CGparameter fp_Texture_ScreenNormalMap;
4022         CGparameter fp_Texture_ScreenDiffuse;
4023         CGparameter fp_Texture_ScreenSpecular;
4024         CGparameter fp_Texture_ReflectMask;
4025         CGparameter fp_Texture_ReflectCube;
4026         CGparameter fp_Alpha;
4027         CGparameter fp_BloomBlur_Parameters;
4028         CGparameter fp_ClientTime;
4029         CGparameter fp_Color_Ambient;
4030         CGparameter fp_Color_Diffuse;
4031         CGparameter fp_Color_Specular;
4032         CGparameter fp_Color_Glow;
4033         CGparameter fp_Color_Pants;
4034         CGparameter fp_Color_Shirt;
4035         CGparameter fp_DeferredColor_Ambient;
4036         CGparameter fp_DeferredColor_Diffuse;
4037         CGparameter fp_DeferredColor_Specular;
4038         CGparameter fp_DeferredMod_Diffuse;
4039         CGparameter fp_DeferredMod_Specular;
4040         CGparameter fp_DistortScaleRefractReflect;
4041         CGparameter fp_EyePosition;
4042         CGparameter fp_FogColor;
4043         CGparameter fp_FogHeightFade;
4044         CGparameter fp_FogPlane;
4045         CGparameter fp_FogPlaneViewDist;
4046         CGparameter fp_FogRangeRecip;
4047         CGparameter fp_LightColor;
4048         CGparameter fp_LightDir;
4049         CGparameter fp_LightPosition;
4050         CGparameter fp_OffsetMapping_Scale;
4051         CGparameter fp_PixelSize;
4052         CGparameter fp_ReflectColor;
4053         CGparameter fp_ReflectFactor;
4054         CGparameter fp_ReflectOffset;
4055         CGparameter fp_RefractColor;
4056         CGparameter fp_Saturation;
4057         CGparameter fp_ScreenCenterRefractReflect;
4058         CGparameter fp_ScreenScaleRefractReflect;
4059         CGparameter fp_ScreenToDepth;
4060         CGparameter fp_ShadowMap_Parameters;
4061         CGparameter fp_ShadowMap_TextureScale;
4062         CGparameter fp_SpecularPower;
4063         CGparameter fp_UserVec1;
4064         CGparameter fp_UserVec2;
4065         CGparameter fp_UserVec3;
4066         CGparameter fp_UserVec4;
4067         CGparameter fp_ViewTintColor;
4068         CGparameter fp_ViewToLight;
4069         CGparameter fp_PixelToScreenTexCoord;
4070         CGparameter fp_ModelToReflectCube;
4071         CGparameter fp_BloomColorSubtract;
4072         CGparameter fp_NormalmapScrollBlend;
4073 }
4074 r_cg_permutation_t;
4075
4076 /// information about each possible shader permutation
4077 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4078 /// currently selected permutation
4079 r_cg_permutation_t *r_cg_permutation;
4080 /// storage for permutations linked in the hash table
4081 memexpandablearray_t r_cg_permutationarray;
4082
4083 #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));}}
4084
4085 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4086 {
4087         //unsigned int hashdepth = 0;
4088         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4089         r_cg_permutation_t *p;
4090         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4091         {
4092                 if (p->mode == mode && p->permutation == permutation)
4093                 {
4094                         //if (hashdepth > 10)
4095                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4096                         return p;
4097                 }
4098                 //hashdepth++;
4099         }
4100         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4101         p->mode = mode;
4102         p->permutation = permutation;
4103         p->hashnext = r_cg_permutationhash[mode][hashindex];
4104         r_cg_permutationhash[mode][hashindex] = p;
4105         //if (hashdepth > 10)
4106         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4107         return p;
4108 }
4109
4110 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4111 {
4112         char *shaderstring;
4113         if (!filename || !filename[0])
4114                 return NULL;
4115         if (!strcmp(filename, "cg/default.cg"))
4116         {
4117                 if (!cgshaderstring)
4118                 {
4119                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4120                         if (cgshaderstring)
4121                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4122                         else
4123                                 cgshaderstring = (char *)builtincgshaderstring;
4124                 }
4125                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4126                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4127                 return shaderstring;
4128         }
4129         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4130         if (shaderstring)
4131         {
4132                 if (printfromdisknotice)
4133                         Con_DPrintf("from disk %s... ", filename);
4134                 return shaderstring;
4135         }
4136         return shaderstring;
4137 }
4138
4139 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4140 {
4141         // TODO: load or create .fp and .vp shader files
4142 }
4143
4144 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4145 {
4146         int i;
4147         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4148         int vertstring_length = 0;
4149         int geomstring_length = 0;
4150         int fragstring_length = 0;
4151         char *t;
4152         char *vertexstring, *geometrystring, *fragmentstring;
4153         char *vertstring, *geomstring, *fragstring;
4154         char permutationname[256];
4155         char cachename[256];
4156         CGprofile vertexProfile;
4157         CGprofile fragmentProfile;
4158         int vertstrings_count = 0;
4159         int geomstrings_count = 0;
4160         int fragstrings_count = 0;
4161         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4162         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4163         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4164
4165         if (p->compiled)
4166                 return;
4167         p->compiled = true;
4168         p->vprogram = NULL;
4169         p->fprogram = NULL;
4170
4171         permutationname[0] = 0;
4172         cachename[0] = 0;
4173         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4174         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4175         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4176
4177         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4178         strlcat(cachename, "cg/", sizeof(cachename));
4179
4180         // the first pretext is which type of shader to compile as
4181         // (later these will all be bound together as a program object)
4182         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4183         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4184         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4185
4186         // the second pretext is the mode (for example a light source)
4187         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4188         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4189         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4190         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4191         strlcat(cachename, modeinfo->name, sizeof(cachename));
4192
4193         // now add all the permutation pretexts
4194         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4195         {
4196                 if (permutation & (1<<i))
4197                 {
4198                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4199                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4200                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4201                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4202                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4203                 }
4204                 else
4205                 {
4206                         // keep line numbers correct
4207                         vertstrings_list[vertstrings_count++] = "\n";
4208                         geomstrings_list[geomstrings_count++] = "\n";
4209                         fragstrings_list[fragstrings_count++] = "\n";
4210                 }
4211         }
4212
4213         // add static parms
4214         R_CompileShader_AddStaticParms(mode, permutation);
4215         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4216         vertstrings_count += shaderstaticparms_count;
4217         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4218         geomstrings_count += shaderstaticparms_count;
4219         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4220         fragstrings_count += shaderstaticparms_count;
4221
4222         // replace spaces in the cachename with _ characters
4223         for (i = 0;cachename[i];i++)
4224                 if (cachename[i] == ' ')
4225                         cachename[i] = '_';
4226
4227         // now append the shader text itself
4228         vertstrings_list[vertstrings_count++] = vertexstring;
4229         geomstrings_list[geomstrings_count++] = geometrystring;
4230         fragstrings_list[fragstrings_count++] = fragmentstring;
4231
4232         // if any sources were NULL, clear the respective list
4233         if (!vertexstring)
4234                 vertstrings_count = 0;
4235         if (!geometrystring)
4236                 geomstrings_count = 0;
4237         if (!fragmentstring)
4238                 fragstrings_count = 0;
4239
4240         vertstring_length = 0;
4241         for (i = 0;i < vertstrings_count;i++)
4242                 vertstring_length += strlen(vertstrings_list[i]);
4243         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4244         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4245                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4246
4247         geomstring_length = 0;
4248         for (i = 0;i < geomstrings_count;i++)
4249                 geomstring_length += strlen(geomstrings_list[i]);
4250         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4251         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4252                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4253
4254         fragstring_length = 0;
4255         for (i = 0;i < fragstrings_count;i++)
4256                 fragstring_length += strlen(fragstrings_list[i]);
4257         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4258         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4259                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4260
4261         CHECKGLERROR
4262         CHECKCGERROR
4263         //vertexProfile = CG_PROFILE_ARBVP1;
4264         //fragmentProfile = CG_PROFILE_ARBFP1;
4265         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4266         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4267         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4268         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4269         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4270         CHECKGLERROR
4271
4272         // try to load the cached shader, or generate one
4273         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4274
4275         // if caching failed, do a dynamic compile for now
4276         CHECKCGERROR
4277         if (vertstring[0] && !p->vprogram)
4278                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4279         CHECKCGERROR
4280         if (fragstring[0] && !p->fprogram)
4281                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4282         CHECKCGERROR
4283
4284         // look up all the uniform variable names we care about, so we don't
4285         // have to look them up every time we set them
4286         if (p->vprogram)
4287         {
4288                 CHECKCGERROR
4289                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4290                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4291                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4292                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4293                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4294                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4295                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4296                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4297                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4298                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4299                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4300                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4301                 CHECKCGERROR
4302         }
4303         if (p->fprogram)
4304         {
4305                 CHECKCGERROR
4306                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4307                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4308                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4309                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4310                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4311                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4312                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4313                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4314                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4315                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4316                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4317                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4318                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4319                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4320                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4321                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4322                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4323                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4324                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4325                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4326                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4327                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4328                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4329                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4330                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4331                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4332                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4333                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4334                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4335                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4336                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4337                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4338                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4339                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4340                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4341                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4342                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4343                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4344                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4345                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4346                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4347                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4348                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4349                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4350                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4351                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4352                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4353                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4354                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4355                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4356                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4357                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4358                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4359                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4360                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4361                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4362                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4363                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4364                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4365                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4366                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4367                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4368                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4369                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4370                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4371                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4372                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4373                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4374                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4375                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4376                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4377                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4378                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4379                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4380                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4381                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4382                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4383                 p->fp_NormalmapScrollBlend       = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4384                 CHECKCGERROR
4385         }
4386
4387         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4388                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4389         else
4390                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4391
4392         // free the strings
4393         if (vertstring)
4394                 Mem_Free(vertstring);
4395         if (geomstring)
4396                 Mem_Free(geomstring);
4397         if (fragstring)
4398                 Mem_Free(fragstring);
4399         if (vertexstring)
4400                 Mem_Free(vertexstring);
4401         if (geometrystring)
4402                 Mem_Free(geometrystring);
4403         if (fragmentstring)
4404                 Mem_Free(fragmentstring);
4405 }
4406
4407 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4408 {
4409         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4410         CHECKGLERROR
4411         CHECKCGERROR
4412         if (r_cg_permutation != perm)
4413         {
4414                 r_cg_permutation = perm;
4415                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4416                 {
4417                         if (!r_cg_permutation->compiled)
4418                                 R_CG_CompilePermutation(perm, mode, permutation);
4419                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4420                         {
4421                                 // remove features until we find a valid permutation
4422                                 int i;
4423                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4424                                 {
4425                                         // reduce i more quickly whenever it would not remove any bits
4426                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4427                                         if (!(permutation & j))
4428                                                 continue;
4429                                         permutation -= j;
4430                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4431                                         if (!r_cg_permutation->compiled)
4432                                                 R_CG_CompilePermutation(perm, mode, permutation);
4433                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4434                                                 break;
4435                                 }
4436                                 if (i >= SHADERPERMUTATION_COUNT)
4437                                 {
4438                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4439                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4440                                         return; // no bit left to clear, entire mode is broken
4441                                 }
4442                         }
4443                 }
4444                 CHECKGLERROR
4445                 CHECKCGERROR
4446                 if (r_cg_permutation->vprogram)
4447                 {
4448                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4449                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4450                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4451                 }
4452                 else
4453                 {
4454                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4455                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4456                 }
4457                 if (r_cg_permutation->fprogram)
4458                 {
4459                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4460                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4461                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4462                 }
4463                 else
4464                 {
4465                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4466                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4467                 }
4468         }
4469         CHECKCGERROR
4470         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4471         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4472         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4473 }
4474
4475 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4476 {
4477         cgGLSetTextureParameter(param, R_GetTexture(tex));
4478         cgGLEnableTextureParameter(param);
4479 }
4480 #endif
4481
4482 #ifdef SUPPORTD3D
4483
4484 #ifdef SUPPORTD3D
4485 #include <d3d9.h>
4486 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4487 extern D3DCAPS9 vid_d3d9caps;
4488 #endif
4489
4490 struct r_hlsl_permutation_s;
4491 typedef struct r_hlsl_permutation_s
4492 {
4493         /// hash lookup data
4494         struct r_hlsl_permutation_s *hashnext;
4495         unsigned int mode;
4496         unsigned int permutation;
4497
4498         /// indicates if we have tried compiling this permutation already
4499         qboolean compiled;
4500         /// NULL if compilation failed
4501         IDirect3DVertexShader9 *vertexshader;
4502         IDirect3DPixelShader9 *pixelshader;
4503 }
4504 r_hlsl_permutation_t;
4505
4506 typedef enum D3DVSREGISTER_e
4507 {
4508         D3DVSREGISTER_TexMatrix = 0, // float4x4
4509         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4510         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4511         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4512         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4513         D3DVSREGISTER_ModelToLight = 20, // float4x4
4514         D3DVSREGISTER_EyePosition = 24,
4515         D3DVSREGISTER_FogPlane = 25,
4516         D3DVSREGISTER_LightDir = 26,
4517         D3DVSREGISTER_LightPosition = 27,
4518 }
4519 D3DVSREGISTER_t;
4520
4521 typedef enum D3DPSREGISTER_e
4522 {
4523         D3DPSREGISTER_Alpha = 0,
4524         D3DPSREGISTER_BloomBlur_Parameters = 1,
4525         D3DPSREGISTER_ClientTime = 2,
4526         D3DPSREGISTER_Color_Ambient = 3,
4527         D3DPSREGISTER_Color_Diffuse = 4,
4528         D3DPSREGISTER_Color_Specular = 5,
4529         D3DPSREGISTER_Color_Glow = 6,
4530         D3DPSREGISTER_Color_Pants = 7,
4531         D3DPSREGISTER_Color_Shirt = 8,
4532         D3DPSREGISTER_DeferredColor_Ambient = 9,
4533         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4534         D3DPSREGISTER_DeferredColor_Specular = 11,
4535         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4536         D3DPSREGISTER_DeferredMod_Specular = 13,
4537         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4538         D3DPSREGISTER_EyePosition = 15, // unused
4539         D3DPSREGISTER_FogColor = 16,
4540         D3DPSREGISTER_FogHeightFade = 17,
4541         D3DPSREGISTER_FogPlane = 18,
4542         D3DPSREGISTER_FogPlaneViewDist = 19,
4543         D3DPSREGISTER_FogRangeRecip = 20,
4544         D3DPSREGISTER_LightColor = 21,
4545         D3DPSREGISTER_LightDir = 22, // unused
4546         D3DPSREGISTER_LightPosition = 23,
4547         D3DPSREGISTER_OffsetMapping_Scale = 24,
4548         D3DPSREGISTER_PixelSize = 25,
4549         D3DPSREGISTER_ReflectColor = 26,
4550         D3DPSREGISTER_ReflectFactor = 27,
4551         D3DPSREGISTER_ReflectOffset = 28,
4552         D3DPSREGISTER_RefractColor = 29,
4553         D3DPSREGISTER_Saturation = 30,
4554         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4555         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4556         D3DPSREGISTER_ScreenToDepth = 33,
4557         D3DPSREGISTER_ShadowMap_Parameters = 34,
4558         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4559         D3DPSREGISTER_SpecularPower = 36,
4560         D3DPSREGISTER_UserVec1 = 37,
4561         D3DPSREGISTER_UserVec2 = 38,
4562         D3DPSREGISTER_UserVec3 = 39,
4563         D3DPSREGISTER_UserVec4 = 40,
4564         D3DPSREGISTER_ViewTintColor = 41,
4565         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4566         D3DPSREGISTER_BloomColorSubtract = 43,
4567         D3DPSREGISTER_ViewToLight = 44, // float4x4
4568         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4569         D3DPSREGISTER_NormalmapScrollBlend = 52,
4570         // next at 53
4571 }
4572 D3DPSREGISTER_t;
4573
4574 /// information about each possible shader permutation
4575 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4576 /// currently selected permutation
4577 r_hlsl_permutation_t *r_hlsl_permutation;
4578 /// storage for permutations linked in the hash table
4579 memexpandablearray_t r_hlsl_permutationarray;
4580
4581 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4582 {
4583         //unsigned int hashdepth = 0;
4584         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4585         r_hlsl_permutation_t *p;
4586         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4587         {
4588                 if (p->mode == mode && p->permutation == permutation)
4589                 {
4590                         //if (hashdepth > 10)
4591                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4592                         return p;
4593                 }
4594                 //hashdepth++;
4595         }
4596         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4597         p->mode = mode;
4598         p->permutation = permutation;
4599         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4600         r_hlsl_permutationhash[mode][hashindex] = p;
4601         //if (hashdepth > 10)
4602         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4603         return p;
4604 }
4605
4606 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4607 {
4608         char *shaderstring;
4609         if (!filename || !filename[0])
4610                 return NULL;
4611         if (!strcmp(filename, "hlsl/default.hlsl"))
4612         {
4613                 if (!hlslshaderstring)
4614                 {
4615                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4616                         if (hlslshaderstring)
4617                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4618                         else
4619                                 hlslshaderstring = (char *)builtincgshaderstring;
4620                 }
4621                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4622                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4623                 return shaderstring;
4624         }
4625         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4626         if (shaderstring)
4627         {
4628                 if (printfromdisknotice)
4629                         Con_DPrintf("from disk %s... ", filename);
4630                 return shaderstring;
4631         }
4632         return shaderstring;
4633 }
4634
4635 #include <d3dx9.h>
4636 //#include <d3dx9shader.h>
4637 //#include <d3dx9mesh.h>
4638
4639 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4640 {
4641         DWORD *vsbin = NULL;
4642         DWORD *psbin = NULL;
4643         fs_offset_t vsbinsize;
4644         fs_offset_t psbinsize;
4645 //      IDirect3DVertexShader9 *vs = NULL;
4646 //      IDirect3DPixelShader9 *ps = NULL;
4647         ID3DXBuffer *vslog = NULL;
4648         ID3DXBuffer *vsbuffer = NULL;
4649         ID3DXConstantTable *vsconstanttable = NULL;
4650         ID3DXBuffer *pslog = NULL;
4651         ID3DXBuffer *psbuffer = NULL;
4652         ID3DXConstantTable *psconstanttable = NULL;
4653         int vsresult = 0;
4654         int psresult = 0;
4655         char temp[MAX_INPUTLINE];
4656         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4657         qboolean debugshader = gl_paranoid.integer != 0;
4658         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4659         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4660         if (!debugshader)
4661         {
4662                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4663                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4664         }
4665         if ((!vsbin && vertstring) || (!psbin && fragstring))
4666         {
4667                 const char* dllnames_d3dx9 [] =
4668                 {
4669                         "d3dx9_43.dll",
4670                         "d3dx9_42.dll",
4671                         "d3dx9_41.dll",
4672                         "d3dx9_40.dll",
4673                         "d3dx9_39.dll",
4674                         "d3dx9_38.dll",
4675                         "d3dx9_37.dll",
4676                         "d3dx9_36.dll",
4677                         "d3dx9_35.dll",
4678                         "d3dx9_34.dll",
4679                         "d3dx9_33.dll",
4680                         "d3dx9_32.dll",
4681                         "d3dx9_31.dll",
4682                         "d3dx9_30.dll",
4683                         "d3dx9_29.dll",
4684                         "d3dx9_28.dll",
4685                         "d3dx9_27.dll",
4686                         "d3dx9_26.dll",
4687                         "d3dx9_25.dll",
4688                         "d3dx9_24.dll",
4689                         NULL
4690                 };
4691                 dllhandle_t d3dx9_dll = NULL;
4692                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4693                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4694                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4695                 dllfunction_t d3dx9_dllfuncs[] =
4696                 {
4697                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4698                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4699                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4700                         {NULL, NULL}
4701                 };
4702                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4703                 {
4704                         DWORD shaderflags = 0;
4705                         if (debugshader)
4706                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4707                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4708                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4709                         if (vertstring && vertstring[0])
4710                         {
4711                                 if (debugshader)
4712                                 {
4713 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4714 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4715                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4716                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4717                                 }
4718                                 else
4719                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4720                                 if (vsbuffer)
4721                                 {
4722                                         vsbinsize = vsbuffer->GetBufferSize();
4723                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4724                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4725                                         vsbuffer->Release();
4726                                 }
4727                                 if (vslog)
4728                                 {
4729                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4730                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4731                                         vslog->Release();
4732                                 }
4733                         }
4734                         if (fragstring && fragstring[0])
4735                         {
4736                                 if (debugshader)
4737                                 {
4738 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4739 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4740                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4741                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4742                                 }
4743                                 else
4744                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4745                                 if (psbuffer)
4746                                 {
4747                                         psbinsize = psbuffer->GetBufferSize();
4748                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4749                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4750                                         psbuffer->Release();
4751                                 }
4752                                 if (pslog)
4753                                 {
4754                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4755                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4756                                         pslog->Release();
4757                                 }
4758                         }
4759                         Sys_UnloadLibrary(&d3dx9_dll);
4760                 }
4761                 else
4762                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4763         }
4764         if (vsbin && psbin)
4765         {
4766                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4767                 if (FAILED(vsresult))
4768                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4769                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4770                 if (FAILED(psresult))
4771                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4772         }
4773         // free the shader data
4774         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4775         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4776 }
4777
4778 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4779 {
4780         int i;
4781         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4782         int vertstring_length = 0;
4783         int geomstring_length = 0;
4784         int fragstring_length = 0;
4785         char *t;
4786         char *vertexstring, *geometrystring, *fragmentstring;
4787         char *vertstring, *geomstring, *fragstring;
4788         char permutationname[256];
4789         char cachename[256];
4790         int vertstrings_count = 0;
4791         int geomstrings_count = 0;
4792         int fragstrings_count = 0;
4793         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4794         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4795         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4796
4797         if (p->compiled)
4798                 return;
4799         p->compiled = true;
4800         p->vertexshader = NULL;
4801         p->pixelshader = NULL;
4802
4803         permutationname[0] = 0;
4804         cachename[0] = 0;
4805         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4806         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4807         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4808
4809         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4810         strlcat(cachename, "hlsl/", sizeof(cachename));
4811
4812         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4813         vertstrings_count = 0;
4814         geomstrings_count = 0;
4815         fragstrings_count = 0;
4816         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4817         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4818         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4819
4820         // the first pretext is which type of shader to compile as
4821         // (later these will all be bound together as a program object)
4822         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4823         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4824         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4825
4826         // the second pretext is the mode (for example a light source)
4827         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4828         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4829         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4830         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4831         strlcat(cachename, modeinfo->name, sizeof(cachename));
4832
4833         // now add all the permutation pretexts
4834         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4835         {
4836                 if (permutation & (1<<i))
4837                 {
4838                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4839                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4840                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4841                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4842                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4843                 }
4844                 else
4845                 {
4846                         // keep line numbers correct
4847                         vertstrings_list[vertstrings_count++] = "\n";
4848                         geomstrings_list[geomstrings_count++] = "\n";
4849                         fragstrings_list[fragstrings_count++] = "\n";
4850                 }
4851         }
4852
4853         // add static parms
4854         R_CompileShader_AddStaticParms(mode, permutation);
4855         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4856         vertstrings_count += shaderstaticparms_count;
4857         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4858         geomstrings_count += shaderstaticparms_count;
4859         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4860         fragstrings_count += shaderstaticparms_count;
4861
4862         // replace spaces in the cachename with _ characters
4863         for (i = 0;cachename[i];i++)
4864                 if (cachename[i] == ' ')
4865                         cachename[i] = '_';
4866
4867         // now append the shader text itself
4868         vertstrings_list[vertstrings_count++] = vertexstring;
4869         geomstrings_list[geomstrings_count++] = geometrystring;
4870         fragstrings_list[fragstrings_count++] = fragmentstring;
4871
4872         // if any sources were NULL, clear the respective list
4873         if (!vertexstring)
4874                 vertstrings_count = 0;
4875         if (!geometrystring)
4876                 geomstrings_count = 0;
4877         if (!fragmentstring)
4878                 fragstrings_count = 0;
4879
4880         vertstring_length = 0;
4881         for (i = 0;i < vertstrings_count;i++)
4882                 vertstring_length += strlen(vertstrings_list[i]);
4883         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4884         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4885                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4886
4887         geomstring_length = 0;
4888         for (i = 0;i < geomstrings_count;i++)
4889                 geomstring_length += strlen(geomstrings_list[i]);
4890         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4891         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4892                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4893
4894         fragstring_length = 0;
4895         for (i = 0;i < fragstrings_count;i++)
4896                 fragstring_length += strlen(fragstrings_list[i]);
4897         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4898         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4899                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4900
4901         // try to load the cached shader, or generate one
4902         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4903
4904         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4905                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4906         else
4907                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4908
4909         // free the strings
4910         if (vertstring)
4911                 Mem_Free(vertstring);
4912         if (geomstring)
4913                 Mem_Free(geomstring);
4914         if (fragstring)
4915                 Mem_Free(fragstring);
4916         if (vertexstring)
4917                 Mem_Free(vertexstring);
4918         if (geometrystring)
4919                 Mem_Free(geometrystring);
4920         if (fragmentstring)
4921                 Mem_Free(fragmentstring);
4922 }
4923
4924 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4925 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4926 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);}
4927 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);}
4928 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);}
4929 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);}
4930
4931 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4932 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4933 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);}
4934 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);}
4935 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);}
4936 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);}
4937
4938 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4939 {
4940         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4941         if (r_hlsl_permutation != perm)
4942         {
4943                 r_hlsl_permutation = perm;
4944                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4945                 {
4946                         if (!r_hlsl_permutation->compiled)
4947                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4948                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4949                         {
4950                                 // remove features until we find a valid permutation
4951                                 int i;
4952                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4953                                 {
4954                                         // reduce i more quickly whenever it would not remove any bits
4955                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4956                                         if (!(permutation & j))
4957                                                 continue;
4958                                         permutation -= j;
4959                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4960                                         if (!r_hlsl_permutation->compiled)
4961                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4962                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4963                                                 break;
4964                                 }
4965                                 if (i >= SHADERPERMUTATION_COUNT)
4966                                 {
4967                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4968                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4969                                         return; // no bit left to clear, entire mode is broken
4970                                 }
4971                         }
4972                 }
4973                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4974                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4975         }
4976         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4977         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4978         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4979 }
4980 #endif
4981
4982 void R_GLSL_Restart_f(void)
4983 {
4984         unsigned int i, limit;
4985         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4986                 Mem_Free(glslshaderstring);
4987         glslshaderstring = NULL;
4988         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4989                 Mem_Free(cgshaderstring);
4990         cgshaderstring = NULL;
4991         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4992                 Mem_Free(hlslshaderstring);
4993         hlslshaderstring = NULL;
4994         switch(vid.renderpath)
4995         {
4996         case RENDERPATH_D3D9:
4997 #ifdef SUPPORTD3D
4998                 {
4999                         r_hlsl_permutation_t *p;
5000                         r_hlsl_permutation = NULL;
5001 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5002 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5003 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5004 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5005                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
5006                         for (i = 0;i < limit;i++)
5007                         {
5008                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
5009                                 {
5010                                         if (p->vertexshader)
5011                                                 IDirect3DVertexShader9_Release(p->vertexshader);
5012                                         if (p->pixelshader)
5013                                                 IDirect3DPixelShader9_Release(p->pixelshader);
5014                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
5015                                 }
5016                         }
5017                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
5018                 }
5019 #endif
5020                 break;
5021         case RENDERPATH_D3D10:
5022                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5023                 break;
5024         case RENDERPATH_D3D11:
5025                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5026                 break;
5027         case RENDERPATH_GL20:
5028                 {
5029                         r_glsl_permutation_t *p;
5030                         r_glsl_permutation = NULL;
5031                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
5032                         for (i = 0;i < limit;i++)
5033                         {
5034                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
5035                                 {
5036                                         GL_Backend_FreeProgram(p->program);
5037                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5038                                 }
5039                         }
5040                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5041                 }
5042                 break;
5043         case RENDERPATH_CGGL:
5044 #ifdef SUPPORTCG
5045                 {
5046                         r_cg_permutation_t *p;
5047                         r_cg_permutation = NULL;
5048                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5049                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5050                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5051                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5052                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5053                         for (i = 0;i < limit;i++)
5054                         {
5055                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5056                                 {
5057                                         if (p->vprogram)
5058                                                 cgDestroyProgram(p->vprogram);
5059                                         if (p->fprogram)
5060                                                 cgDestroyProgram(p->fprogram);
5061                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5062                                 }
5063                         }
5064                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5065                 }
5066 #endif
5067                 break;
5068         case RENDERPATH_GL13:
5069         case RENDERPATH_GL11:
5070                 break;
5071         }
5072 }
5073
5074 void R_GLSL_DumpShader_f(void)
5075 {
5076         int i;
5077         qfile_t *file;
5078
5079         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5080         if (file)
5081         {
5082                 FS_Print(file, "/* The engine may define the following macros:\n");
5083                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5084                 for (i = 0;i < SHADERMODE_COUNT;i++)
5085                         FS_Print(file, glslshadermodeinfo[i].pretext);
5086                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5087                         FS_Print(file, shaderpermutationinfo[i].pretext);
5088                 FS_Print(file, "*/\n");
5089                 FS_Print(file, builtinshaderstring);
5090                 FS_Close(file);
5091                 Con_Printf("glsl/default.glsl written\n");
5092         }
5093         else
5094                 Con_Printf("failed to write to glsl/default.glsl\n");
5095
5096 #ifdef SUPPORTCG
5097         file = FS_OpenRealFile("cg/default.cg", "w", false);
5098         if (file)
5099         {
5100                 FS_Print(file, "/* The engine may define the following macros:\n");
5101                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5102                 for (i = 0;i < SHADERMODE_COUNT;i++)
5103                         FS_Print(file, cgshadermodeinfo[i].pretext);
5104                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5105                         FS_Print(file, shaderpermutationinfo[i].pretext);
5106                 FS_Print(file, "*/\n");
5107                 FS_Print(file, builtincgshaderstring);
5108                 FS_Close(file);
5109                 Con_Printf("cg/default.cg written\n");
5110         }
5111         else
5112                 Con_Printf("failed to write to cg/default.cg\n");
5113 #endif
5114
5115 #ifdef SUPPORTD3D
5116         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5117         if (file)
5118         {
5119                 FS_Print(file, "/* The engine may define the following macros:\n");
5120                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5121                 for (i = 0;i < SHADERMODE_COUNT;i++)
5122                         FS_Print(file, hlslshadermodeinfo[i].pretext);
5123                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5124                         FS_Print(file, shaderpermutationinfo[i].pretext);
5125                 FS_Print(file, "*/\n");
5126                 FS_Print(file, builtincgshaderstring);
5127                 FS_Close(file);
5128                 Con_Printf("hlsl/default.hlsl written\n");
5129         }
5130         else
5131                 Con_Printf("failed to write to hlsl/default.hlsl\n");
5132 #endif
5133 }
5134
5135 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5136 {
5137         if (!second)
5138                 texturemode = GL_MODULATE;
5139         switch (vid.renderpath)
5140         {
5141         case RENDERPATH_D3D9:
5142 #ifdef SUPPORTD3D
5143                 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))));
5144                 R_Mesh_TexBind(GL20TU_FIRST , first );
5145                 R_Mesh_TexBind(GL20TU_SECOND, second);
5146 #endif
5147                 break;
5148         case RENDERPATH_D3D10:
5149                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5150                 break;
5151         case RENDERPATH_D3D11:
5152                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5153                 break;
5154         case RENDERPATH_GL20:
5155                 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))));
5156                 R_Mesh_TexBind(GL20TU_FIRST , first );
5157                 R_Mesh_TexBind(GL20TU_SECOND, second);
5158                 break;
5159         case RENDERPATH_CGGL:
5160 #ifdef SUPPORTCG
5161                 CHECKCGERROR
5162                 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))));
5163                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5164                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5165 #endif
5166                 break;
5167         case RENDERPATH_GL13:
5168                 R_Mesh_TexBind(0, first );
5169                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5170                 R_Mesh_TexBind(1, second);
5171                 if (second)
5172                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5173                 break;
5174         case RENDERPATH_GL11:
5175                 R_Mesh_TexBind(0, first );
5176                 break;
5177         }
5178 }
5179
5180 void R_SetupShader_DepthOrShadow(void)
5181 {
5182         switch (vid.renderpath)
5183         {
5184         case RENDERPATH_D3D9:
5185 #ifdef SUPPORTD3D
5186                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5187 #endif
5188                 break;
5189         case RENDERPATH_D3D10:
5190                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5191                 break;
5192         case RENDERPATH_D3D11:
5193                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5194                 break;
5195         case RENDERPATH_GL20:
5196                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5197                 break;
5198         case RENDERPATH_CGGL:
5199 #ifdef SUPPORTCG
5200                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5201 #endif
5202                 break;
5203         case RENDERPATH_GL13:
5204                 R_Mesh_TexBind(0, 0);
5205                 R_Mesh_TexBind(1, 0);
5206                 break;
5207         case RENDERPATH_GL11:
5208                 R_Mesh_TexBind(0, 0);
5209                 break;
5210         }
5211 }
5212
5213 void R_SetupShader_ShowDepth(void)
5214 {
5215         switch (vid.renderpath)
5216         {
5217         case RENDERPATH_D3D9:
5218 #ifdef SUPPORTHLSL
5219                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5220 #endif
5221                 break;
5222         case RENDERPATH_D3D10:
5223                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5224                 break;
5225         case RENDERPATH_D3D11:
5226                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5227                 break;
5228         case RENDERPATH_GL20:
5229                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5230                 break;
5231         case RENDERPATH_CGGL:
5232 #ifdef SUPPORTCG
5233                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5234 #endif
5235                 break;
5236         case RENDERPATH_GL13:
5237                 break;
5238         case RENDERPATH_GL11:
5239                 break;
5240         }
5241 }
5242
5243 extern qboolean r_shadow_usingdeferredprepass;
5244 extern cvar_t r_shadow_deferred_8bitrange;
5245 extern rtexture_t *r_shadow_attenuationgradienttexture;
5246 extern rtexture_t *r_shadow_attenuation2dtexture;
5247 extern rtexture_t *r_shadow_attenuation3dtexture;
5248 extern qboolean r_shadow_usingshadowmap2d;
5249 extern qboolean r_shadow_usingshadowmaportho;
5250 extern float r_shadow_shadowmap_texturescale[2];
5251 extern float r_shadow_shadowmap_parameters[4];
5252 extern qboolean r_shadow_shadowmapvsdct;
5253 extern qboolean r_shadow_shadowmapsampler;
5254 extern int r_shadow_shadowmappcf;
5255 extern rtexture_t *r_shadow_shadowmap2dtexture;
5256 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5257 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5258 extern matrix4x4_t r_shadow_shadowmapmatrix;
5259 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5260 extern int r_shadow_prepass_width;
5261 extern int r_shadow_prepass_height;
5262 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5263 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5264 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5265 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5266 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5267 extern cvar_t gl_mesh_separatearrays;
5268 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5269 {
5270         // a blendfunc allows colormod if:
5271         // a) it can never keep the destination pixel invariant, or
5272         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5273         // this is to prevent unintended side effects from colormod
5274
5275         // in formulas:
5276         // IF there is a (s, sa) for which for all (d, da),
5277         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5278         // THEN, for this (s, sa) and all (colormod, d, da):
5279         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5280         // OBVIOUSLY, this means that
5281         //   s*colormod * src(s*colormod, d, sa, da) = 0
5282         //   dst(s*colormod, d, sa, da)              = 1
5283
5284         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5285
5286         // main condition to leave dst color invariant:
5287         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5288         //   src == GL_ZERO:
5289         //     s * 0 + d * dst(s, d, sa, da) == d
5290         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5291         //       => colormod is a problem for GL_SRC_COLOR only
5292         //   src == GL_ONE:
5293         //     s + d * dst(s, d, sa, da) == d
5294         //       => s == 0
5295         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5296         //       => colormod is never problematic for these
5297         //   src == GL_SRC_COLOR:
5298         //     s*s + d * dst(s, d, sa, da) == d
5299         //       => s == 0
5300         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5301         //       => colormod is never problematic for these
5302         //   src == GL_ONE_MINUS_SRC_COLOR:
5303         //     s*(1-s) + d * dst(s, d, sa, da) == d
5304         //       => s == 0 or s == 1
5305         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5306         //       => colormod is a problem for GL_SRC_COLOR only
5307         //   src == GL_DST_COLOR
5308         //     s*d + d * dst(s, d, sa, da) == d
5309         //       => s == 1
5310         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5311         //       => colormod is always a problem
5312         //     or
5313         //       => s == 0
5314         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5315         //       => colormod is never problematic for these
5316         //       => BUT, we do not know s! We must assume it is problematic
5317         //       then... except in GL_ONE case, where we know all invariant
5318         //       cases are fine
5319         //   src == GL_ONE_MINUS_DST_COLOR
5320         //     s*(1-d) + d * dst(s, d, sa, da) == d
5321         //       => s == 0 (1-d is impossible to handle for our desired result)
5322         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5323         //       => colormod is never problematic for these
5324         //   src == GL_SRC_ALPHA
5325         //     s*sa + d * dst(s, d, sa, da) == d
5326         //       => s == 0, or sa == 0
5327         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5328         //       => colormod breaks in the case GL_SRC_COLOR only
5329         //   src == GL_ONE_MINUS_SRC_ALPHA
5330         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5331         //       => s == 0, or sa == 1
5332         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5333         //       => colormod breaks in the case GL_SRC_COLOR only
5334         //   src == GL_DST_ALPHA
5335         //     s*da + d * dst(s, d, sa, da) == d
5336         //       => s == 0
5337         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5338         //       => colormod is never problematic for these
5339
5340         switch(src)
5341         {
5342                 case GL_ZERO:
5343                 case GL_ONE_MINUS_SRC_COLOR:
5344                 case GL_SRC_ALPHA:
5345                 case GL_ONE_MINUS_SRC_ALPHA:
5346                         if(dst == GL_SRC_COLOR)
5347                                 return false;
5348                         return true;
5349                 case GL_ONE:
5350                 case GL_SRC_COLOR:
5351                 case GL_ONE_MINUS_DST_COLOR:
5352                 case GL_DST_ALPHA:
5353                 case GL_ONE_MINUS_DST_ALPHA:
5354                         return true;
5355                 case GL_DST_COLOR:
5356                         if(dst == GL_ONE)
5357                                 return true;
5358                         return false;
5359                 default:
5360                         return false;
5361         }
5362 }
5363 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)
5364 {
5365         // select a permutation of the lighting shader appropriate to this
5366         // combination of texture, entity, light source, and fogging, only use the
5367         // minimum features necessary to avoid wasting rendering time in the
5368         // fragment shader on features that are not being used
5369         unsigned int permutation = 0;
5370         unsigned int mode = 0;
5371         qboolean allow_colormod;
5372         static float dummy_colormod[3] = {1, 1, 1};
5373         float *colormod = rsurface.colormod;
5374         float m16f[16];
5375         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5376         if (rsurfacepass == RSURFPASS_BACKGROUND)
5377         {
5378                 // distorted background
5379                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5380                 {
5381                         mode = SHADERMODE_WATER;
5382                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
5383                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
5384                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5385                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5386                 }
5387                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5388                 {
5389                         mode = SHADERMODE_REFRACTION;
5390                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5391                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5392                 }
5393                 else
5394                 {
5395                         mode = SHADERMODE_GENERIC;
5396                         permutation |= SHADERPERMUTATION_DIFFUSE;
5397                         GL_BlendFunc(GL_ONE, GL_ZERO);
5398                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5399                 }
5400                 GL_AlphaTest(false);
5401         }
5402         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5403         {
5404                 if (r_glsl_offsetmapping.integer)
5405                 {
5406                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5407                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5408                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5409                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5410                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5411                         {
5412                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5413                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5414                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5415                         }
5416                 }
5417                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5418                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5419                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5420                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5421                 // normalmap (deferred prepass), may use alpha test on diffuse
5422                 mode = SHADERMODE_DEFERREDGEOMETRY;
5423                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5424                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5425                 GL_AlphaTest(false);
5426                 GL_BlendFunc(GL_ONE, GL_ZERO);
5427                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5428         }
5429         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5430         {
5431                 if (r_glsl_offsetmapping.integer)
5432                 {
5433                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5434                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5435                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5436                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5437                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5438                         {
5439                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5440                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5441                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5442                         }
5443                 }
5444                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5445                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5446                 // light source
5447                 mode = SHADERMODE_LIGHTSOURCE;
5448                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5449                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5450                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5451                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5452                 if (diffusescale > 0)
5453                         permutation |= SHADERPERMUTATION_DIFFUSE;
5454                 if (specularscale > 0)
5455                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5456                 if (r_refdef.fogenabled)
5457                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5458                 if (rsurface.texture->colormapping)
5459                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5460                 if (r_shadow_usingshadowmap2d)
5461                 {
5462                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5463                         if(r_shadow_shadowmapvsdct)
5464                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5465
5466                         if (r_shadow_shadowmapsampler)
5467                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5468                         if (r_shadow_shadowmappcf > 1)
5469                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5470                         else if (r_shadow_shadowmappcf)
5471                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5472                 }
5473                 if (rsurface.texture->reflectmasktexture)
5474                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5475                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5476                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5477                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5478         }
5479         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5480         {
5481                 if (r_glsl_offsetmapping.integer)
5482                 {
5483                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5484                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5485                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5486                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5487                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5488                         {
5489                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5490                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5491                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5492                         }
5493                 }
5494                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5495                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5496                 // unshaded geometry (fullbright or ambient model lighting)
5497                 mode = SHADERMODE_FLATCOLOR;
5498                 ambientscale = diffusescale = specularscale = 0;
5499                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5500                         permutation |= SHADERPERMUTATION_GLOW;
5501                 if (r_refdef.fogenabled)
5502                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5503                 if (rsurface.texture->colormapping)
5504                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5505                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5506                 {
5507                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5508                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5509
5510                         if (r_shadow_shadowmapsampler)
5511                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5512                         if (r_shadow_shadowmappcf > 1)
5513                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5514                         else if (r_shadow_shadowmappcf)
5515                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5516                 }
5517                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5518                         permutation |= SHADERPERMUTATION_REFLECTION;
5519                 if (rsurface.texture->reflectmasktexture)
5520                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5521                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5522                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5523                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5524         }
5525         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5526         {
5527                 if (r_glsl_offsetmapping.integer)
5528                 {
5529                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5530                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5531                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5532                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5533                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5534                         {
5535                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5536                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5537                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5538                         }
5539                 }
5540                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5541                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5542                 // directional model lighting
5543                 mode = SHADERMODE_LIGHTDIRECTION;
5544                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5545                         permutation |= SHADERPERMUTATION_GLOW;
5546                 permutation |= SHADERPERMUTATION_DIFFUSE;
5547                 if (specularscale > 0)
5548                         permutation |= SHADERPERMUTATION_SPECULAR;
5549                 if (r_refdef.fogenabled)
5550                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5551                 if (rsurface.texture->colormapping)
5552                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5553                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5554                 {
5555                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5556                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5557
5558                         if (r_shadow_shadowmapsampler)
5559                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5560                         if (r_shadow_shadowmappcf > 1)
5561                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5562                         else if (r_shadow_shadowmappcf)
5563                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5564                 }
5565                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5566                         permutation |= SHADERPERMUTATION_REFLECTION;
5567                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5568                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5569                 if (rsurface.texture->reflectmasktexture)
5570                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5571                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5572                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5573                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5574         }
5575         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5576         {
5577                 if (r_glsl_offsetmapping.integer)
5578                 {
5579                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5580                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5581                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5582                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5583                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5584                         {
5585                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5586                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5587                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5588                         }
5589                 }
5590                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5591                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5592                 // ambient model lighting
5593                 mode = SHADERMODE_LIGHTDIRECTION;
5594                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5595                         permutation |= SHADERPERMUTATION_GLOW;
5596                 if (r_refdef.fogenabled)
5597                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5598                 if (rsurface.texture->colormapping)
5599                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5600                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5601                 {
5602                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5603                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5604
5605                         if (r_shadow_shadowmapsampler)
5606                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5607                         if (r_shadow_shadowmappcf > 1)
5608                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5609                         else if (r_shadow_shadowmappcf)
5610                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5611                 }
5612                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5613                         permutation |= SHADERPERMUTATION_REFLECTION;
5614                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5615                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5616                 if (rsurface.texture->reflectmasktexture)
5617                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5618                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5619                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5620                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5621         }
5622         else
5623         {
5624                 if (r_glsl_offsetmapping.integer)
5625                 {
5626                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5627                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5628                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5629                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5630                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5631                         {
5632                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5633                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5634                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5635                         }
5636                 }
5637                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5638                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5639                 // lightmapped wall
5640                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5641                         permutation |= SHADERPERMUTATION_GLOW;
5642                 if (r_refdef.fogenabled)
5643                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5644                 if (rsurface.texture->colormapping)
5645                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5646                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5647                 {
5648                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5649                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5650
5651                         if (r_shadow_shadowmapsampler)
5652                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5653                         if (r_shadow_shadowmappcf > 1)
5654                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5655                         else if (r_shadow_shadowmappcf)
5656                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5657                 }
5658                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5659                         permutation |= SHADERPERMUTATION_REFLECTION;
5660                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5661                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5662                 if (rsurface.texture->reflectmasktexture)
5663                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5664                 if (FAKELIGHT_ENABLED)
5665                 {
5666                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5667                         mode = SHADERMODE_FAKELIGHT;
5668                         permutation |= SHADERPERMUTATION_DIFFUSE;
5669                         if (specularscale > 0)
5670                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5671                 }
5672                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5673                 {
5674                         // deluxemapping (light direction texture)
5675                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5676                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5677                         else
5678                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5679                         permutation |= SHADERPERMUTATION_DIFFUSE;
5680                         if (specularscale > 0)
5681                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5682                 }
5683                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5684                 {
5685                         // fake deluxemapping (uniform light direction in tangentspace)
5686                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5687                         permutation |= SHADERPERMUTATION_DIFFUSE;
5688                         if (specularscale > 0)
5689                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5690                 }
5691                 else if (rsurface.uselightmaptexture)
5692                 {
5693                         // ordinary lightmapping (q1bsp, q3bsp)
5694                         mode = SHADERMODE_LIGHTMAP;
5695                 }
5696                 else
5697                 {
5698                         // ordinary vertex coloring (q3bsp)
5699                         mode = SHADERMODE_VERTEXCOLOR;
5700                 }
5701                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5702                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5703                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5704         }
5705         if(!allow_colormod)
5706                 colormod = dummy_colormod;
5707         switch(vid.renderpath)
5708         {
5709         case RENDERPATH_D3D9:
5710 #ifdef SUPPORTD3D
5711                 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);
5712                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5713                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5714                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5715                 if (mode == SHADERMODE_LIGHTSOURCE)
5716                 {
5717                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5718                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5719                 }
5720                 else
5721                 {
5722                         if (mode == SHADERMODE_LIGHTDIRECTION)                                   
5723                         {
5724                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5725                         }
5726                 }
5727                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5728                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5729                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5730                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5731                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5732
5733                 if (mode == SHADERMODE_LIGHTSOURCE)
5734                 {
5735                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5736                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5737                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5738                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5739                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5740
5741                         // additive passes are only darkened by fog, not tinted
5742                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5743                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5744                 }
5745                 else
5746                 {
5747                         if (mode == SHADERMODE_FLATCOLOR)
5748                         {
5749                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5750                         }
5751                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5752                         {
5753                                 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]);
5754                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5755                                 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);
5756                                 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);
5757                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5758                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5759                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5760                         }
5761                         else
5762                         {
5763                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5764                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5765                                 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);
5766                                 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);
5767                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5768                         }
5769                         // additive passes are only darkened by fog, not tinted
5770                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5771                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5772                         else
5773                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5774                         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);
5775                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5776                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5777                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5778                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5779                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5780                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5781                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5782                         if (mode == SHADERMODE_WATER)
5783                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5784                 }
5785                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5786                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5787                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5788                 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));
5789                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5790                 if (rsurface.texture->pantstexture)
5791                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5792                 else
5793                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5794                 if (rsurface.texture->shirttexture)
5795                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5796                 else
5797                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5798                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5799                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5800                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5801                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5802                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5803                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5804                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5805
5806                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5807                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5808                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5809                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5810                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5811                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5812                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5813                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5814                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5815                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5816                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5817                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5818                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5819                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5820                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5821                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5822                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5823                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5824                 {
5825                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5826                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5827                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5828                 }
5829                 else
5830                 {
5831                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5832                 }
5833 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5834 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5835                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5836                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5837                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5838                 {
5839                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5840                         if (rsurface.rtlight)
5841                         {
5842                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5843                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5844                         }
5845                 }
5846 #endif
5847                 break;
5848         case RENDERPATH_D3D10:
5849                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5850                 break;
5851         case RENDERPATH_D3D11:
5852                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5853                 break;
5854         case RENDERPATH_GL20:
5855                 if (gl_mesh_separatearrays.integer)
5856                 {
5857                         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);
5858                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5859                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5860                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5861                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5862                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5863                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5864                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5865                 }
5866                 else
5867                 {
5868                         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);
5869                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5870                 }
5871                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5872                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5873                 if (mode == SHADERMODE_LIGHTSOURCE)
5874                 {
5875                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5876                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5877                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5878                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5879                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5880                         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);
5881         
5882                         // additive passes are only darkened by fog, not tinted
5883                         if (r_glsl_permutation->loc_FogColor >= 0)
5884                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5885                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5886                 }
5887                 else
5888                 {
5889                         if (mode == SHADERMODE_FLATCOLOR)
5890                         {
5891                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5892                         }
5893                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5894                         {
5895                                 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]);
5896                                 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]);
5897                                 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);
5898                                 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);
5899                                 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);
5900                                 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]);
5901                                 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]);
5902                         }
5903                         else
5904                         {
5905                                 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]);
5906                                 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]);
5907                                 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);
5908                                 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);
5909                                 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);
5910                         }
5911                         // additive passes are only darkened by fog, not tinted
5912                         if (r_glsl_permutation->loc_FogColor >= 0)
5913                         {
5914                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5915                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5916                                 else
5917                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5918                         }
5919                         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);
5920                         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]);
5921                         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]);
5922                         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]);
5923                         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]);
5924                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5925                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5926                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5927                         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]);
5928                 }
5929                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5930                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5931                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5932                 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]);
5933                 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]);
5934
5935                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5936                 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));
5937                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5938                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5939                 {
5940                         if (rsurface.texture->pantstexture)
5941                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5942                         else
5943                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5944                 }
5945                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5946                 {
5947                         if (rsurface.texture->shirttexture)
5948                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5949                         else
5950                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5951                 }
5952                 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]);
5953                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5954                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5955                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5956                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5957                 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]);
5958                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5959
5960         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5961         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5962         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5963                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5964                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5965                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5966                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5967                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5968                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5969                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5970                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5971                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5972                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5973                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5974                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5975                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5976                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5977                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5978                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5979                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5980                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5981                 {
5982                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5983                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5984                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5985                 }
5986                 else
5987                 {
5988                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5989                 }
5990 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5991 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5992                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5993                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5994                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5995                 {
5996                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5997                         if (rsurface.rtlight)
5998                         {
5999                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
6000                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
6001                         }
6002                 }
6003                 CHECKGLERROR
6004                 break;
6005         case RENDERPATH_CGGL:
6006 #ifdef SUPPORTCG
6007                 if (gl_mesh_separatearrays.integer)
6008                 {
6009                         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);
6010                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
6011                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
6012                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
6013                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
6014                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6015                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6016                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6017                 }
6018                 else
6019                 {
6020                         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);
6021                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6022                 }
6023                 R_SetupShader_SetPermutationCG(mode, permutation);
6024                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6025                 if (mode == SHADERMODE_LIGHTSOURCE)
6026                 {
6027                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6028                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6029                 }
6030                 else
6031                 {
6032                         if (mode == SHADERMODE_LIGHTDIRECTION)
6033                         {
6034                                 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
6035                         }
6036                 }
6037                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6038                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6039                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6040                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6041                 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
6042                 CHECKGLERROR
6043
6044                 if (mode == SHADERMODE_LIGHTSOURCE)
6045                 {
6046                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6047                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6048                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6049                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6050                         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
6051
6052                         // additive passes are only darkened by fog, not tinted
6053                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6054                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6055                 }
6056                 else
6057                 {
6058                         if (mode == SHADERMODE_FLATCOLOR)
6059                         {
6060                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6061                         }
6062                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6063                         {
6064                                 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
6065                                 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
6066                                 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
6067                                 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
6068                                 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
6069                                 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
6070                                 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
6071                         }
6072                         else
6073                         {
6074                                 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
6075                                 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
6076                                 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
6077                                 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
6078                                 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
6079                         }
6080                         // additive passes are only darkened by fog, not tinted
6081                         if (r_cg_permutation->fp_FogColor)
6082                         {
6083                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6084                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6085                                 else
6086                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6087                                 CHECKCGERROR
6088                         }
6089                         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
6090                         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
6091                         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
6092                         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
6093                         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
6094                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6095                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6096                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6097                         if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6098                 }
6099                 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
6100                 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
6101                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6102                 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
6103                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6104                 if (r_cg_permutation->fp_Color_Pants)
6105                 {
6106                         if (rsurface.texture->pantstexture)
6107                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6108                         else
6109                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6110                         CHECKCGERROR
6111                 }
6112                 if (r_cg_permutation->fp_Color_Shirt)
6113                 {
6114                         if (rsurface.texture->shirttexture)
6115                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6116                         else
6117                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6118                         CHECKCGERROR
6119                 }
6120                 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
6121                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6122                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6123                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6124                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6125                 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
6126                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6127
6128         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
6129         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
6130         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
6131                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
6132                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
6133                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
6134                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
6135                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
6136                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
6137                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
6138                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
6139                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
6140                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
6141                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
6142                 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
6143                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
6144                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
6145                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6146                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6147                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6148                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6149                 {
6150                         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
6151                         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
6152                         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
6153                 }
6154                 else
6155                 {
6156                         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
6157                 }
6158                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6159                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6160                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
6161                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
6162                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6163                 {
6164                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6165                         if (rsurface.rtlight)
6166                         {
6167                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6168                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6169                         }
6170                 }
6171
6172                 CHECKGLERROR
6173 #endif
6174                 break;
6175         case RENDERPATH_GL13:
6176         case RENDERPATH_GL11:
6177                 break;
6178         }
6179 }
6180
6181 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6182 {
6183         // select a permutation of the lighting shader appropriate to this
6184         // combination of texture, entity, light source, and fogging, only use the
6185         // minimum features necessary to avoid wasting rendering time in the
6186         // fragment shader on features that are not being used
6187         unsigned int permutation = 0;
6188         unsigned int mode = 0;
6189         const float *lightcolorbase = rtlight->currentcolor;
6190         float ambientscale = rtlight->ambientscale;
6191         float diffusescale = rtlight->diffusescale;
6192         float specularscale = rtlight->specularscale;
6193         // this is the location of the light in view space
6194         vec3_t viewlightorigin;
6195         // this transforms from view space (camera) to light space (cubemap)
6196         matrix4x4_t viewtolight;
6197         matrix4x4_t lighttoview;
6198         float viewtolight16f[16];
6199         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6200         // light source
6201         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6202         if (rtlight->currentcubemap != r_texture_whitecube)
6203                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6204         if (diffusescale > 0)
6205                 permutation |= SHADERPERMUTATION_DIFFUSE;
6206         if (specularscale > 0)
6207                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6208         if (r_shadow_usingshadowmap2d)
6209         {
6210                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6211                 if (r_shadow_shadowmapvsdct)
6212                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6213
6214                 if (r_shadow_shadowmapsampler)
6215                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6216                 if (r_shadow_shadowmappcf > 1)
6217                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6218                 else if (r_shadow_shadowmappcf)
6219                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6220         }
6221         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6222         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6223         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6224         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6225         switch(vid.renderpath)
6226         {
6227         case RENDERPATH_D3D9:
6228 #ifdef SUPPORTD3D
6229                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6230                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6231                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6232                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6233                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6234                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6235                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6236                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6237                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6238                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6239                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6240
6241                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6242                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
6243                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6244                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6245                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
6246                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6247 #endif
6248                 break;
6249         case RENDERPATH_D3D10:
6250                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6251                 break;
6252         case RENDERPATH_D3D11:
6253                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6254                 break;
6255         case RENDERPATH_GL20:
6256                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6257                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6258                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6259                 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);
6260                 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);
6261                 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);
6262                 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]);
6263                 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]);
6264                 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));
6265                 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]);
6266                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6267
6268                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6269                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6270                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6271                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6272                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6273                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6274                 break;
6275         case RENDERPATH_CGGL:
6276 #ifdef SUPPORTCG
6277                 R_SetupShader_SetPermutationCG(mode, permutation);
6278                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6279                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6280                 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
6281                 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
6282                 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
6283                 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
6284                 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
6285                 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
6286                 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
6287                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6288
6289                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6290                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6291                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6292                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6293                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6294                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6295 #endif
6296                 break;
6297         case RENDERPATH_GL13:
6298         case RENDERPATH_GL11:
6299                 break;
6300         }
6301 }
6302
6303 #define SKINFRAME_HASH 1024
6304
6305 typedef struct
6306 {
6307         int loadsequence; // incremented each level change
6308         memexpandablearray_t array;
6309         skinframe_t *hash[SKINFRAME_HASH];
6310 }
6311 r_skinframe_t;
6312 r_skinframe_t r_skinframe;
6313
6314 void R_SkinFrame_PrepareForPurge(void)
6315 {
6316         r_skinframe.loadsequence++;
6317         // wrap it without hitting zero
6318         if (r_skinframe.loadsequence >= 200)
6319                 r_skinframe.loadsequence = 1;
6320 }
6321
6322 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6323 {
6324         if (!skinframe)
6325                 return;
6326         // mark the skinframe as used for the purging code
6327         skinframe->loadsequence = r_skinframe.loadsequence;
6328 }
6329
6330 void R_SkinFrame_Purge(void)
6331 {
6332         int i;
6333         skinframe_t *s;
6334         for (i = 0;i < SKINFRAME_HASH;i++)
6335         {
6336                 for (s = r_skinframe.hash[i];s;s = s->next)
6337                 {
6338                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6339                         {
6340                                 if (s->merged == s->base)
6341                                         s->merged = NULL;
6342                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6343                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6344                                 R_PurgeTexture(s->merged);s->merged = NULL;
6345                                 R_PurgeTexture(s->base  );s->base   = NULL;
6346                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6347                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6348                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6349                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6350                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6351                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6352                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6353                                 s->loadsequence = 0;
6354                         }
6355                 }
6356         }
6357 }
6358
6359 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6360         skinframe_t *item;
6361         char basename[MAX_QPATH];
6362
6363         Image_StripImageExtension(name, basename, sizeof(basename));
6364
6365         if( last == NULL ) {
6366                 int hashindex;
6367                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6368                 item = r_skinframe.hash[hashindex];
6369         } else {
6370                 item = last->next;
6371         }
6372
6373         // linearly search through the hash bucket
6374         for( ; item ; item = item->next ) {
6375                 if( !strcmp( item->basename, basename ) ) {
6376                         return item;
6377                 }
6378         }
6379         return NULL;
6380 }
6381
6382 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6383 {
6384         skinframe_t *item;
6385         int hashindex;
6386         char basename[MAX_QPATH];
6387
6388         Image_StripImageExtension(name, basename, sizeof(basename));
6389
6390         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6391         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6392                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6393                         break;
6394
6395         if (!item) {
6396                 rtexture_t *dyntexture;
6397                 // check whether its a dynamic texture
6398                 dyntexture = CL_GetDynTexture( basename );
6399                 if (!add && !dyntexture)
6400                         return NULL;
6401                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6402                 memset(item, 0, sizeof(*item));
6403                 strlcpy(item->basename, basename, sizeof(item->basename));
6404                 item->base = dyntexture; // either NULL or dyntexture handle
6405                 item->textureflags = textureflags;
6406                 item->comparewidth = comparewidth;
6407                 item->compareheight = compareheight;
6408                 item->comparecrc = comparecrc;
6409                 item->next = r_skinframe.hash[hashindex];
6410                 r_skinframe.hash[hashindex] = item;
6411         }
6412         else if( item->base == NULL )
6413         {
6414                 rtexture_t *dyntexture;
6415                 // check whether its a dynamic texture
6416                 // 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]
6417                 dyntexture = CL_GetDynTexture( basename );
6418                 item->base = dyntexture; // either NULL or dyntexture handle
6419         }
6420
6421         R_SkinFrame_MarkUsed(item);
6422         return item;
6423 }
6424
6425 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6426         { \
6427                 unsigned long long avgcolor[5], wsum; \
6428                 int pix, comp, w; \
6429                 avgcolor[0] = 0; \
6430                 avgcolor[1] = 0; \
6431                 avgcolor[2] = 0; \
6432                 avgcolor[3] = 0; \
6433                 avgcolor[4] = 0; \
6434                 wsum = 0; \
6435                 for(pix = 0; pix < cnt; ++pix) \
6436                 { \
6437                         w = 0; \
6438                         for(comp = 0; comp < 3; ++comp) \
6439                                 w += getpixel; \
6440                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6441                         { \
6442                                 ++wsum; \
6443                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6444                                 w = getpixel; \
6445                                 for(comp = 0; comp < 3; ++comp) \
6446                                         avgcolor[comp] += getpixel * w; \
6447                                 avgcolor[3] += w; \
6448                         } \
6449                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6450                         avgcolor[4] += getpixel; \
6451                 } \
6452                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6453                         avgcolor[3] = 1; \
6454                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6455                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6456                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6457                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6458         }
6459
6460 extern cvar_t gl_picmip;
6461 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6462 {
6463         int j;
6464         unsigned char *pixels;
6465         unsigned char *bumppixels;
6466         unsigned char *basepixels = NULL;
6467         int basepixels_width = 0;
6468         int basepixels_height = 0;
6469         skinframe_t *skinframe;
6470         rtexture_t *ddsbase = NULL;
6471         qboolean ddshasalpha = false;
6472         float ddsavgcolor[4];
6473         char basename[MAX_QPATH];
6474         int miplevel = R_PicmipForFlags(textureflags);
6475         int savemiplevel = miplevel;
6476         int mymiplevel;
6477
6478         if (cls.state == ca_dedicated)
6479                 return NULL;
6480
6481         // return an existing skinframe if already loaded
6482         // if loading of the first image fails, don't make a new skinframe as it
6483         // would cause all future lookups of this to be missing
6484         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6485         if (skinframe && skinframe->base)
6486                 return skinframe;
6487
6488         Image_StripImageExtension(name, basename, sizeof(basename));
6489
6490         // check for DDS texture file first
6491         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6492         {
6493                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6494                 if (basepixels == NULL)
6495                         return NULL;
6496         }
6497
6498         // FIXME handle miplevel
6499
6500         if (developer_loading.integer)
6501                 Con_Printf("loading skin \"%s\"\n", name);
6502
6503         // we've got some pixels to store, so really allocate this new texture now
6504         if (!skinframe)
6505                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6506         skinframe->stain = NULL;
6507         skinframe->merged = NULL;
6508         skinframe->base = NULL;
6509         skinframe->pants = NULL;
6510         skinframe->shirt = NULL;
6511         skinframe->nmap = NULL;
6512         skinframe->gloss = NULL;
6513         skinframe->glow = NULL;
6514         skinframe->fog = NULL;
6515         skinframe->reflect = NULL;
6516         skinframe->hasalpha = false;
6517
6518         if (ddsbase)
6519         {
6520                 skinframe->base = ddsbase;
6521                 skinframe->hasalpha = ddshasalpha;
6522                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6523                 if (r_loadfog && skinframe->hasalpha)
6524                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6525                 //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]);
6526         }
6527         else
6528         {
6529                 basepixels_width = image_width;
6530                 basepixels_height = image_height;
6531                 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);
6532                 if (textureflags & TEXF_ALPHA)
6533                 {
6534                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6535                         {
6536                                 if (basepixels[j] < 255)
6537                                 {
6538                                         skinframe->hasalpha = true;
6539                                         break;
6540                                 }
6541                         }
6542                         if (r_loadfog && skinframe->hasalpha)
6543                         {
6544                                 // has transparent pixels
6545                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6546                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6547                                 {
6548                                         pixels[j+0] = 255;
6549                                         pixels[j+1] = 255;
6550                                         pixels[j+2] = 255;
6551                                         pixels[j+3] = basepixels[j+3];
6552                                 }
6553                                 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);
6554                                 Mem_Free(pixels);
6555                         }
6556                 }
6557                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6558                 //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]);
6559                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6560                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6561                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6562                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6563         }
6564
6565         if (r_loaddds)
6566         {
6567                 mymiplevel = savemiplevel;
6568                 if (r_loadnormalmap)
6569                         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);
6570                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6571                 if (r_loadgloss)
6572                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6573                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6574                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6575                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6576         }
6577
6578         // _norm is the name used by tenebrae and has been adopted as standard
6579         if (r_loadnormalmap && skinframe->nmap == NULL)
6580         {
6581                 mymiplevel = savemiplevel;
6582                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6583                 {
6584                         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);
6585                         Mem_Free(pixels);
6586                         pixels = NULL;
6587                 }
6588                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6589                 {
6590                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6591                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6592                         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);
6593                         Mem_Free(pixels);
6594                         Mem_Free(bumppixels);
6595                 }
6596                 else if (r_shadow_bumpscale_basetexture.value > 0)
6597                 {
6598                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6599                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6600                         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);
6601                         Mem_Free(pixels);
6602                 }
6603                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6604                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6605         }
6606
6607         // _luma is supported only for tenebrae compatibility
6608         // _glow is the preferred name
6609         mymiplevel = savemiplevel;
6610         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))))
6611         {
6612                 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);
6613                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6614                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6615                 Mem_Free(pixels);pixels = NULL;
6616         }
6617
6618         mymiplevel = savemiplevel;
6619         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6620         {
6621                 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);
6622                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6623                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6624                 Mem_Free(pixels);
6625                 pixels = NULL;
6626         }
6627
6628         mymiplevel = savemiplevel;
6629         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6630         {
6631                 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);
6632                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6633                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6634                 Mem_Free(pixels);
6635                 pixels = NULL;
6636         }
6637
6638         mymiplevel = savemiplevel;
6639         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6640         {
6641                 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);
6642                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6643                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6644                 Mem_Free(pixels);
6645                 pixels = NULL;
6646         }
6647
6648         mymiplevel = savemiplevel;
6649         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6650         {
6651                 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);
6652                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6653                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6654                 Mem_Free(pixels);
6655                 pixels = NULL;
6656         }
6657
6658         if (basepixels)
6659                 Mem_Free(basepixels);
6660
6661         return skinframe;
6662 }
6663
6664 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6665 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6666 {
6667         int i;
6668         unsigned char *temp1, *temp2;
6669         skinframe_t *skinframe;
6670
6671         if (cls.state == ca_dedicated)
6672                 return NULL;
6673
6674         // if already loaded just return it, otherwise make a new skinframe
6675         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6676         if (skinframe && skinframe->base)
6677                 return skinframe;
6678
6679         skinframe->stain = NULL;
6680         skinframe->merged = NULL;
6681         skinframe->base = NULL;
6682         skinframe->pants = NULL;
6683         skinframe->shirt = NULL;
6684         skinframe->nmap = NULL;
6685         skinframe->gloss = NULL;
6686         skinframe->glow = NULL;
6687         skinframe->fog = NULL;
6688         skinframe->reflect = NULL;
6689         skinframe->hasalpha = false;
6690
6691         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6692         if (!skindata)
6693                 return NULL;
6694
6695         if (developer_loading.integer)
6696                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6697
6698         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6699         {
6700                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6701                 temp2 = temp1 + width * height * 4;
6702                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6703                 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);
6704                 Mem_Free(temp1);
6705         }
6706         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6707         if (textureflags & TEXF_ALPHA)
6708         {
6709                 for (i = 3;i < width * height * 4;i += 4)
6710                 {
6711                         if (skindata[i] < 255)
6712                         {
6713                                 skinframe->hasalpha = true;
6714                                 break;
6715                         }
6716                 }
6717                 if (r_loadfog && skinframe->hasalpha)
6718                 {
6719                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6720                         memcpy(fogpixels, skindata, width * height * 4);
6721                         for (i = 0;i < width * height * 4;i += 4)
6722                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6723                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6724                         Mem_Free(fogpixels);
6725                 }
6726         }
6727
6728         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6729         //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]);
6730
6731         return skinframe;
6732 }
6733
6734 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6735 {
6736         int i;
6737         int featuresmask;
6738         skinframe_t *skinframe;
6739
6740         if (cls.state == ca_dedicated)
6741                 return NULL;
6742
6743         // if already loaded just return it, otherwise make a new skinframe
6744         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6745         if (skinframe && skinframe->base)
6746                 return skinframe;
6747
6748         skinframe->stain = NULL;
6749         skinframe->merged = NULL;
6750         skinframe->base = NULL;
6751         skinframe->pants = NULL;
6752         skinframe->shirt = NULL;
6753         skinframe->nmap = NULL;
6754         skinframe->gloss = NULL;
6755         skinframe->glow = NULL;
6756         skinframe->fog = NULL;
6757         skinframe->reflect = NULL;
6758         skinframe->hasalpha = false;
6759
6760         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6761         if (!skindata)
6762                 return NULL;
6763
6764         if (developer_loading.integer)
6765                 Con_Printf("loading quake skin \"%s\"\n", name);
6766
6767         // 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)
6768         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6769         memcpy(skinframe->qpixels, skindata, width*height);
6770         skinframe->qwidth = width;
6771         skinframe->qheight = height;
6772
6773         featuresmask = 0;
6774         for (i = 0;i < width * height;i++)
6775                 featuresmask |= palette_featureflags[skindata[i]];
6776
6777         skinframe->hasalpha = false;
6778         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6779         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6780         skinframe->qgeneratemerged = true;
6781         skinframe->qgeneratebase = skinframe->qhascolormapping;
6782         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6783
6784         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6785         //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]);
6786
6787         return skinframe;
6788 }
6789
6790 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6791 {
6792         int width;
6793         int height;
6794         unsigned char *skindata;
6795
6796         if (!skinframe->qpixels)
6797                 return;
6798
6799         if (!skinframe->qhascolormapping)
6800                 colormapped = false;
6801
6802         if (colormapped)
6803         {
6804                 if (!skinframe->qgeneratebase)
6805                         return;
6806         }
6807         else
6808         {
6809                 if (!skinframe->qgeneratemerged)
6810                         return;
6811         }
6812
6813         width = skinframe->qwidth;
6814         height = skinframe->qheight;
6815         skindata = skinframe->qpixels;
6816
6817         if (skinframe->qgeneratenmap)
6818         {
6819                 unsigned char *temp1, *temp2;
6820                 skinframe->qgeneratenmap = false;
6821                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6822                 temp2 = temp1 + width * height * 4;
6823                 // use either a custom palette or the quake palette
6824                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6825                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6826                 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);
6827                 Mem_Free(temp1);
6828         }
6829
6830         if (skinframe->qgenerateglow)
6831         {
6832                 skinframe->qgenerateglow = false;
6833                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6834         }
6835
6836         if (colormapped)
6837         {
6838                 skinframe->qgeneratebase = false;
6839                 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);
6840                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6841                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6842         }
6843         else
6844         {
6845                 skinframe->qgeneratemerged = false;
6846                 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);
6847         }
6848
6849         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6850         {
6851                 Mem_Free(skinframe->qpixels);
6852                 skinframe->qpixels = NULL;
6853         }
6854 }
6855
6856 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)
6857 {
6858         int i;
6859         skinframe_t *skinframe;
6860
6861         if (cls.state == ca_dedicated)
6862                 return NULL;
6863
6864         // if already loaded just return it, otherwise make a new skinframe
6865         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6866         if (skinframe && skinframe->base)
6867                 return skinframe;
6868
6869         skinframe->stain = NULL;
6870         skinframe->merged = NULL;
6871         skinframe->base = NULL;
6872         skinframe->pants = NULL;
6873         skinframe->shirt = NULL;
6874         skinframe->nmap = NULL;
6875         skinframe->gloss = NULL;
6876         skinframe->glow = NULL;
6877         skinframe->fog = NULL;
6878         skinframe->reflect = NULL;
6879         skinframe->hasalpha = false;
6880
6881         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6882         if (!skindata)
6883                 return NULL;
6884
6885         if (developer_loading.integer)
6886                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6887
6888         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6889         if (textureflags & TEXF_ALPHA)
6890         {
6891                 for (i = 0;i < width * height;i++)
6892                 {
6893                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6894                         {
6895                                 skinframe->hasalpha = true;
6896                                 break;
6897                         }
6898                 }
6899                 if (r_loadfog && skinframe->hasalpha)
6900                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6901         }
6902
6903         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6904         //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]);
6905
6906         return skinframe;
6907 }
6908
6909 skinframe_t *R_SkinFrame_LoadMissing(void)
6910 {
6911         skinframe_t *skinframe;
6912
6913         if (cls.state == ca_dedicated)
6914                 return NULL;
6915
6916         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6917         skinframe->stain = NULL;
6918         skinframe->merged = NULL;
6919         skinframe->base = NULL;
6920         skinframe->pants = NULL;
6921         skinframe->shirt = NULL;
6922         skinframe->nmap = NULL;
6923         skinframe->gloss = NULL;
6924         skinframe->glow = NULL;
6925         skinframe->fog = NULL;
6926         skinframe->reflect = NULL;
6927         skinframe->hasalpha = false;
6928
6929         skinframe->avgcolor[0] = rand() / RAND_MAX;
6930         skinframe->avgcolor[1] = rand() / RAND_MAX;
6931         skinframe->avgcolor[2] = rand() / RAND_MAX;
6932         skinframe->avgcolor[3] = 1;
6933
6934         return skinframe;
6935 }
6936
6937 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6938 typedef struct suffixinfo_s
6939 {
6940         const char *suffix;
6941         qboolean flipx, flipy, flipdiagonal;
6942 }
6943 suffixinfo_t;
6944 static suffixinfo_t suffix[3][6] =
6945 {
6946         {
6947                 {"px",   false, false, false},
6948                 {"nx",   false, false, false},
6949                 {"py",   false, false, false},
6950                 {"ny",   false, false, false},
6951                 {"pz",   false, false, false},
6952                 {"nz",   false, false, false}
6953         },
6954         {
6955                 {"posx", false, false, false},
6956                 {"negx", false, false, false},
6957                 {"posy", false, false, false},
6958                 {"negy", false, false, false},
6959                 {"posz", false, false, false},
6960                 {"negz", false, false, false}
6961         },
6962         {
6963                 {"rt",    true, false,  true},
6964                 {"lf",   false,  true,  true},
6965                 {"ft",    true,  true, false},
6966                 {"bk",   false, false, false},
6967                 {"up",    true, false,  true},
6968                 {"dn",    true, false,  true}
6969         }
6970 };
6971
6972 static int componentorder[4] = {0, 1, 2, 3};
6973
6974 rtexture_t *R_LoadCubemap(const char *basename)
6975 {
6976         int i, j, cubemapsize;
6977         unsigned char *cubemappixels, *image_buffer;
6978         rtexture_t *cubemaptexture;
6979         char name[256];
6980         // must start 0 so the first loadimagepixels has no requested width/height
6981         cubemapsize = 0;
6982         cubemappixels = NULL;
6983         cubemaptexture = NULL;
6984         // keep trying different suffix groups (posx, px, rt) until one loads
6985         for (j = 0;j < 3 && !cubemappixels;j++)
6986         {
6987                 // load the 6 images in the suffix group
6988                 for (i = 0;i < 6;i++)
6989                 {
6990                         // generate an image name based on the base and and suffix
6991                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6992                         // load it
6993                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6994                         {
6995                                 // an image loaded, make sure width and height are equal
6996                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6997                                 {
6998                                         // if this is the first image to load successfully, allocate the cubemap memory
6999                                         if (!cubemappixels && image_width >= 1)
7000                                         {
7001                                                 cubemapsize = image_width;
7002                                                 // note this clears to black, so unavailable sides are black
7003                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7004                                         }
7005                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7006                                         if (cubemappixels)
7007                                                 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);
7008                                 }
7009                                 else
7010                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7011                                 // free the image
7012                                 Mem_Free(image_buffer);
7013                         }
7014                 }
7015         }
7016         // if a cubemap loaded, upload it
7017         if (cubemappixels)
7018         {
7019                 if (developer_loading.integer)
7020                         Con_Printf("loading cubemap \"%s\"\n", basename);
7021
7022                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7023                 Mem_Free(cubemappixels);
7024         }
7025         else
7026         {
7027                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7028                 if (developer_loading.integer)
7029                 {
7030                         Con_Printf("(tried tried images ");
7031                         for (j = 0;j < 3;j++)
7032                                 for (i = 0;i < 6;i++)
7033                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7034                         Con_Print(" and was unable to find any of them).\n");
7035                 }
7036         }
7037         return cubemaptexture;
7038 }
7039
7040 rtexture_t *R_GetCubemap(const char *basename)
7041 {
7042         int i;
7043         for (i = 0;i < r_texture_numcubemaps;i++)
7044                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7045                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7046         if (i >= MAX_CUBEMAPS)
7047                 return r_texture_whitecube;
7048         r_texture_numcubemaps++;
7049         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7050         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7051         return r_texture_cubemaps[i].texture;
7052 }
7053
7054 void R_FreeCubemaps(void)
7055 {
7056         int i;
7057         for (i = 0;i < r_texture_numcubemaps;i++)
7058         {
7059                 if (developer_loading.integer)
7060                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7061                 if (r_texture_cubemaps[i].texture)
7062                         R_FreeTexture(r_texture_cubemaps[i].texture);
7063         }
7064         r_texture_numcubemaps = 0;
7065 }
7066
7067 void R_Main_FreeViewCache(void)
7068 {
7069         if (r_refdef.viewcache.entityvisible)
7070                 Mem_Free(r_refdef.viewcache.entityvisible);
7071         if (r_refdef.viewcache.world_pvsbits)
7072                 Mem_Free(r_refdef.viewcache.world_pvsbits);
7073         if (r_refdef.viewcache.world_leafvisible)
7074                 Mem_Free(r_refdef.viewcache.world_leafvisible);
7075         if (r_refdef.viewcache.world_surfacevisible)
7076                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7077         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7078 }
7079
7080 void R_Main_ResizeViewCache(void)
7081 {
7082         int numentities = r_refdef.scene.numentities;
7083         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7084         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7085         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7086         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7087         if (r_refdef.viewcache.maxentities < numentities)
7088         {
7089                 r_refdef.viewcache.maxentities = numentities;
7090                 if (r_refdef.viewcache.entityvisible)
7091                         Mem_Free(r_refdef.viewcache.entityvisible);
7092                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7093         }
7094         if (r_refdef.viewcache.world_numclusters != numclusters)
7095         {
7096                 r_refdef.viewcache.world_numclusters = numclusters;
7097                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7098                 if (r_refdef.viewcache.world_pvsbits)
7099                         Mem_Free(r_refdef.viewcache.world_pvsbits);
7100                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7101         }
7102         if (r_refdef.viewcache.world_numleafs != numleafs)
7103         {
7104                 r_refdef.viewcache.world_numleafs = numleafs;
7105                 if (r_refdef.viewcache.world_leafvisible)
7106                         Mem_Free(r_refdef.viewcache.world_leafvisible);
7107                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7108         }
7109         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7110         {
7111                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7112                 if (r_refdef.viewcache.world_surfacevisible)
7113                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
7114                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7115         }
7116 }
7117
7118 extern rtexture_t *loadingscreentexture;
7119 void gl_main_start(void)
7120 {
7121         loadingscreentexture = NULL;
7122         r_texture_blanknormalmap = NULL;
7123         r_texture_white = NULL;
7124         r_texture_grey128 = NULL;
7125         r_texture_black = NULL;
7126         r_texture_whitecube = NULL;
7127         r_texture_normalizationcube = NULL;
7128         r_texture_fogattenuation = NULL;
7129         r_texture_fogheighttexture = NULL;
7130         r_texture_gammaramps = NULL;
7131         r_texture_numcubemaps = 0;
7132
7133         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
7134         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7135
7136         switch(vid.renderpath)
7137         {
7138         case RENDERPATH_GL20:
7139         case RENDERPATH_CGGL:
7140         case RENDERPATH_D3D9:
7141         case RENDERPATH_D3D10:
7142         case RENDERPATH_D3D11:
7143                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7144                 Cvar_SetValueQuick(&gl_combine, 1);
7145                 Cvar_SetValueQuick(&r_glsl, 1);
7146                 r_loadnormalmap = true;
7147                 r_loadgloss = true;
7148                 r_loadfog = false;
7149                 break;
7150         case RENDERPATH_GL13:
7151                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7152                 Cvar_SetValueQuick(&gl_combine, 1);
7153                 Cvar_SetValueQuick(&r_glsl, 0);
7154                 r_loadnormalmap = false;
7155                 r_loadgloss = false;
7156                 r_loadfog = true;
7157                 break;
7158         case RENDERPATH_GL11:
7159                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7160                 Cvar_SetValueQuick(&gl_combine, 0);
7161                 Cvar_SetValueQuick(&r_glsl, 0);
7162                 r_loadnormalmap = false;
7163                 r_loadgloss = false;
7164                 r_loadfog = true;
7165                 break;
7166         }
7167
7168         R_AnimCache_Free();
7169         R_FrameData_Reset();
7170
7171         r_numqueries = 0;
7172         r_maxqueries = 0;
7173         memset(r_queries, 0, sizeof(r_queries));
7174
7175         r_qwskincache = NULL;
7176         r_qwskincache_size = 0;
7177
7178         // set up r_skinframe loading system for textures
7179         memset(&r_skinframe, 0, sizeof(r_skinframe));
7180         r_skinframe.loadsequence = 1;
7181         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7182
7183         r_main_texturepool = R_AllocTexturePool();
7184         R_BuildBlankTextures();
7185         R_BuildNoTexture();
7186         if (vid.support.arb_texture_cube_map)
7187         {
7188                 R_BuildWhiteCube();
7189                 R_BuildNormalizationCube();
7190         }
7191         r_texture_fogattenuation = NULL;
7192         r_texture_fogheighttexture = NULL;
7193         r_texture_gammaramps = NULL;
7194         //r_texture_fogintensity = NULL;
7195         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7196         memset(&r_waterstate, 0, sizeof(r_waterstate));
7197         r_glsl_permutation = NULL;
7198         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7199         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7200         glslshaderstring = NULL;
7201 #ifdef SUPPORTCG
7202         r_cg_permutation = NULL;
7203         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7204         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7205         cgshaderstring = NULL;
7206 #endif
7207 #ifdef SUPPORTD3D
7208         r_hlsl_permutation = NULL;
7209         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7210         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7211         hlslshaderstring = NULL;
7212 #endif
7213         memset(&r_svbsp, 0, sizeof (r_svbsp));
7214
7215         r_refdef.fogmasktable_density = 0;
7216 }
7217
7218 void gl_main_shutdown(void)
7219 {
7220         R_AnimCache_Free();
7221         R_FrameData_Reset();
7222
7223         R_Main_FreeViewCache();
7224
7225         switch(vid.renderpath)
7226         {
7227         case RENDERPATH_GL11:
7228         case RENDERPATH_GL13:
7229         case RENDERPATH_GL20:
7230         case RENDERPATH_CGGL:
7231                 if (r_maxqueries)
7232                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7233                 break;
7234         case RENDERPATH_D3D9:
7235                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7236                 break;
7237         case RENDERPATH_D3D10:
7238                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7239                 break;
7240         case RENDERPATH_D3D11:
7241                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7242                 break;
7243         }
7244
7245         r_numqueries = 0;
7246         r_maxqueries = 0;
7247         memset(r_queries, 0, sizeof(r_queries));
7248
7249         r_qwskincache = NULL;
7250         r_qwskincache_size = 0;
7251
7252         // clear out the r_skinframe state
7253         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7254         memset(&r_skinframe, 0, sizeof(r_skinframe));
7255
7256         if (r_svbsp.nodes)
7257                 Mem_Free(r_svbsp.nodes);
7258         memset(&r_svbsp, 0, sizeof (r_svbsp));
7259         R_FreeTexturePool(&r_main_texturepool);
7260         loadingscreentexture = NULL;
7261         r_texture_blanknormalmap = NULL;
7262         r_texture_white = NULL;
7263         r_texture_grey128 = NULL;
7264         r_texture_black = NULL;
7265         r_texture_whitecube = NULL;
7266         r_texture_normalizationcube = NULL;
7267         r_texture_fogattenuation = NULL;
7268         r_texture_fogheighttexture = NULL;
7269         r_texture_gammaramps = NULL;
7270         r_texture_numcubemaps = 0;
7271         //r_texture_fogintensity = NULL;
7272         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7273         memset(&r_waterstate, 0, sizeof(r_waterstate));
7274         R_GLSL_Restart_f();
7275 }
7276
7277 extern void CL_ParseEntityLump(char *entitystring);
7278 void gl_main_newmap(void)
7279 {
7280         // FIXME: move this code to client
7281         char *entities, entname[MAX_QPATH];
7282         if (r_qwskincache)
7283                 Mem_Free(r_qwskincache);
7284         r_qwskincache = NULL;
7285         r_qwskincache_size = 0;
7286         if (cl.worldmodel)
7287         {
7288                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7289                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7290                 {
7291                         CL_ParseEntityLump(entities);
7292                         Mem_Free(entities);
7293                         return;
7294                 }
7295                 if (cl.worldmodel->brush.entities)
7296                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7297         }
7298         R_Main_FreeViewCache();
7299
7300         R_FrameData_Reset();
7301 }
7302
7303 void GL_Main_Init(void)
7304 {
7305         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7306
7307         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7308         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7309         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7310         if (gamemode == GAME_NEHAHRA)
7311         {
7312                 Cvar_RegisterVariable (&gl_fogenable);
7313                 Cvar_RegisterVariable (&gl_fogdensity);
7314                 Cvar_RegisterVariable (&gl_fogred);
7315                 Cvar_RegisterVariable (&gl_foggreen);
7316                 Cvar_RegisterVariable (&gl_fogblue);
7317                 Cvar_RegisterVariable (&gl_fogstart);
7318                 Cvar_RegisterVariable (&gl_fogend);
7319                 Cvar_RegisterVariable (&gl_skyclip);
7320         }
7321         Cvar_RegisterVariable(&r_motionblur);
7322         Cvar_RegisterVariable(&r_motionblur_maxblur);
7323         Cvar_RegisterVariable(&r_motionblur_bmin);
7324         Cvar_RegisterVariable(&r_motionblur_vmin);
7325         Cvar_RegisterVariable(&r_motionblur_vmax);
7326         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7327         Cvar_RegisterVariable(&r_motionblur_randomize);
7328         Cvar_RegisterVariable(&r_damageblur);
7329         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7330         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7331         Cvar_RegisterVariable(&r_equalize_entities_by);
7332         Cvar_RegisterVariable(&r_equalize_entities_to);
7333         Cvar_RegisterVariable(&r_depthfirst);
7334         Cvar_RegisterVariable(&r_useinfinitefarclip);
7335         Cvar_RegisterVariable(&r_farclip_base);
7336         Cvar_RegisterVariable(&r_farclip_world);
7337         Cvar_RegisterVariable(&r_nearclip);
7338         Cvar_RegisterVariable(&r_showbboxes);
7339         Cvar_RegisterVariable(&r_showsurfaces);
7340         Cvar_RegisterVariable(&r_showtris);
7341         Cvar_RegisterVariable(&r_shownormals);
7342         Cvar_RegisterVariable(&r_showlighting);
7343         Cvar_RegisterVariable(&r_showshadowvolumes);
7344         Cvar_RegisterVariable(&r_showcollisionbrushes);
7345         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7346         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7347         Cvar_RegisterVariable(&r_showdisabledepthtest);
7348         Cvar_RegisterVariable(&r_drawportals);
7349         Cvar_RegisterVariable(&r_drawentities);
7350         Cvar_RegisterVariable(&r_draw2d);
7351         Cvar_RegisterVariable(&r_drawworld);
7352         Cvar_RegisterVariable(&r_cullentities_trace);
7353         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7354         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7355         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7356         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7357         Cvar_RegisterVariable(&r_drawviewmodel);
7358         Cvar_RegisterVariable(&r_drawexteriormodel);
7359         Cvar_RegisterVariable(&r_speeds);
7360         Cvar_RegisterVariable(&r_fullbrights);
7361         Cvar_RegisterVariable(&r_wateralpha);
7362         Cvar_RegisterVariable(&r_dynamic);
7363         Cvar_RegisterVariable(&r_fakelight);
7364         Cvar_RegisterVariable(&r_fakelight_intensity);
7365         Cvar_RegisterVariable(&r_fullbright);
7366         Cvar_RegisterVariable(&r_shadows);
7367         Cvar_RegisterVariable(&r_shadows_darken);
7368         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7369         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7370         Cvar_RegisterVariable(&r_shadows_throwdistance);
7371         Cvar_RegisterVariable(&r_shadows_throwdirection);
7372         Cvar_RegisterVariable(&r_shadows_focus);
7373         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7374         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7375         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7376         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7377         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7378         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7379         Cvar_RegisterVariable(&r_fog_exp2);
7380         Cvar_RegisterVariable(&r_drawfog);
7381         Cvar_RegisterVariable(&r_transparentdepthmasking);
7382         Cvar_RegisterVariable(&r_texture_dds_load);
7383         Cvar_RegisterVariable(&r_texture_dds_save);
7384         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7385         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7386         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7387         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7388         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7389         Cvar_RegisterVariable(&r_textureunits);
7390         Cvar_RegisterVariable(&gl_combine);
7391         Cvar_RegisterVariable(&r_glsl);
7392         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7393         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7394         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7395         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7396         Cvar_RegisterVariable(&r_glsl_postprocess);
7397         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7398         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7399         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7400         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7401         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
7402         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
7403         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
7404         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
7405
7406         Cvar_RegisterVariable(&r_water);
7407         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7408         Cvar_RegisterVariable(&r_water_clippingplanebias);
7409         Cvar_RegisterVariable(&r_water_refractdistort);
7410         Cvar_RegisterVariable(&r_water_reflectdistort);
7411         Cvar_RegisterVariable(&r_water_scissormode);
7412         Cvar_RegisterVariable(&r_lerpsprites);
7413         Cvar_RegisterVariable(&r_lerpmodels);
7414         Cvar_RegisterVariable(&r_lerplightstyles);
7415         Cvar_RegisterVariable(&r_waterscroll);
7416         Cvar_RegisterVariable(&r_bloom);
7417         Cvar_RegisterVariable(&r_bloom_colorscale);
7418         Cvar_RegisterVariable(&r_bloom_brighten);
7419         Cvar_RegisterVariable(&r_bloom_blur);
7420         Cvar_RegisterVariable(&r_bloom_resolution);
7421         Cvar_RegisterVariable(&r_bloom_colorexponent);
7422         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7423         Cvar_RegisterVariable(&r_hdr);
7424         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7425         Cvar_RegisterVariable(&r_hdr_glowintensity);
7426         Cvar_RegisterVariable(&r_hdr_range);
7427         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7428         Cvar_RegisterVariable(&developer_texturelogging);
7429         Cvar_RegisterVariable(&gl_lightmaps);
7430         Cvar_RegisterVariable(&r_test);
7431         Cvar_RegisterVariable(&r_glsl_saturation);
7432         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7433         Cvar_RegisterVariable(&r_framedatasize);
7434         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7435                 Cvar_SetValue("r_fullbrights", 0);
7436         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7437
7438         Cvar_RegisterVariable(&r_track_sprites);
7439         Cvar_RegisterVariable(&r_track_sprites_flags);
7440         Cvar_RegisterVariable(&r_track_sprites_scalew);
7441         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7442         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7443         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7444 }
7445
7446 extern void R_Textures_Init(void);
7447 extern void GL_Draw_Init(void);
7448 extern void GL_Main_Init(void);
7449 extern void R_Shadow_Init(void);
7450 extern void R_Sky_Init(void);
7451 extern void GL_Surf_Init(void);
7452 extern void R_Particles_Init(void);
7453 extern void R_Explosion_Init(void);
7454 extern void gl_backend_init(void);
7455 extern void Sbar_Init(void);
7456 extern void R_LightningBeams_Init(void);
7457 extern void Mod_RenderInit(void);
7458 extern void Font_Init(void);
7459
7460 void Render_Init(void)
7461 {
7462         gl_backend_init();
7463         R_Textures_Init();
7464         GL_Main_Init();
7465         Font_Init();
7466         GL_Draw_Init();
7467         R_Shadow_Init();
7468         R_Sky_Init();
7469         GL_Surf_Init();
7470         Sbar_Init();
7471         R_Particles_Init();
7472         R_Explosion_Init();
7473         R_LightningBeams_Init();
7474         Mod_RenderInit();
7475 }
7476
7477 /*
7478 ===============
7479 GL_Init
7480 ===============
7481 */
7482 extern char *ENGINE_EXTENSIONS;
7483 void GL_Init (void)
7484 {
7485         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7486         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7487         gl_version = (const char *)qglGetString(GL_VERSION);
7488         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7489
7490         if (!gl_extensions)
7491                 gl_extensions = "";
7492         if (!gl_platformextensions)
7493                 gl_platformextensions = "";
7494
7495         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7496         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7497         Con_Printf("GL_VERSION: %s\n", gl_version);
7498         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7499         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7500
7501         VID_CheckExtensions();
7502
7503         // LordHavoc: report supported extensions
7504         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7505
7506         // clear to black (loading plaque will be seen over this)
7507         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7508 }
7509
7510 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7511 {
7512         int i;
7513         mplane_t *p;
7514         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7515         {
7516                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7517                 if (i == 4)
7518                         continue;
7519                 p = r_refdef.view.frustum + i;
7520                 switch(p->signbits)
7521                 {
7522                 default:
7523                 case 0:
7524                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7525                                 return true;
7526                         break;
7527                 case 1:
7528                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7529                                 return true;
7530                         break;
7531                 case 2:
7532                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7533                                 return true;
7534                         break;
7535                 case 3:
7536                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7537                                 return true;
7538                         break;
7539                 case 4:
7540                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7541                                 return true;
7542                         break;
7543                 case 5:
7544                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7545                                 return true;
7546                         break;
7547                 case 6:
7548                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7549                                 return true;
7550                         break;
7551                 case 7:
7552                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7553                                 return true;
7554                         break;
7555                 }
7556         }
7557         return false;
7558 }
7559
7560 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7561 {
7562         int i;
7563         const mplane_t *p;
7564         for (i = 0;i < numplanes;i++)
7565         {
7566                 p = planes + i;
7567                 switch(p->signbits)
7568                 {
7569                 default:
7570                 case 0:
7571                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7572                                 return true;
7573                         break;
7574                 case 1:
7575                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7576                                 return true;
7577                         break;
7578                 case 2:
7579                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7580                                 return true;
7581                         break;
7582                 case 3:
7583                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7584                                 return true;
7585                         break;
7586                 case 4:
7587                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7588                                 return true;
7589                         break;
7590                 case 5:
7591                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7592                                 return true;
7593                         break;
7594                 case 6:
7595                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7596                                 return true;
7597                         break;
7598                 case 7:
7599                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7600                                 return true;
7601                         break;
7602                 }
7603         }
7604         return false;
7605 }
7606
7607 //==================================================================================
7608
7609 // LordHavoc: this stores temporary data used within the same frame
7610
7611 qboolean r_framedata_failed;
7612 static size_t r_framedata_size;
7613 static size_t r_framedata_current;
7614 static void *r_framedata_base;
7615
7616 void R_FrameData_Reset(void)
7617 {
7618         if (r_framedata_base)
7619                 Mem_Free(r_framedata_base);
7620         r_framedata_base = NULL;
7621         r_framedata_size = 0;
7622         r_framedata_current = 0;
7623         r_framedata_failed = false;
7624 }
7625
7626 void R_FrameData_NewFrame(void)
7627 {
7628         size_t wantedsize;
7629         if (r_framedata_failed)
7630                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7631         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7632         wantedsize = bound(65536, wantedsize, 128*1024*1024);
7633         if (r_framedata_size != wantedsize)
7634         {
7635                 r_framedata_size = wantedsize;
7636                 if (r_framedata_base)
7637                         Mem_Free(r_framedata_base);
7638                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7639         }
7640         r_framedata_current = 0;
7641         r_framedata_failed = false;
7642 }
7643
7644 void *R_FrameData_Alloc(size_t size)
7645 {
7646         void *data;
7647
7648         // align to 16 byte boundary
7649         size = (size + 15) & ~15;
7650         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7651         r_framedata_current += size;
7652
7653         // check overflow
7654         if (r_framedata_current > r_framedata_size)
7655                 r_framedata_failed = true;
7656
7657         // return NULL on everything after a failure
7658         if (r_framedata_failed)
7659                 return NULL;
7660
7661         return data;
7662 }
7663
7664 void *R_FrameData_Store(size_t size, void *data)
7665 {
7666         void *d = R_FrameData_Alloc(size);
7667         if (d)
7668                 memcpy(d, data, size);
7669         return d;
7670 }
7671
7672 //==================================================================================
7673
7674 // LordHavoc: animcache originally written by Echon, rewritten since then
7675
7676 /**
7677  * Animation cache prevents re-generating mesh data for an animated model
7678  * multiple times in one frame for lighting, shadowing, reflections, etc.
7679  */
7680
7681 void R_AnimCache_Free(void)
7682 {
7683 }
7684
7685 void R_AnimCache_ClearCache(void)
7686 {
7687         int i;
7688         entity_render_t *ent;
7689
7690         for (i = 0;i < r_refdef.scene.numentities;i++)
7691         {
7692                 ent = r_refdef.scene.entities[i];
7693                 ent->animcache_vertex3f = NULL;
7694                 ent->animcache_normal3f = NULL;
7695                 ent->animcache_svector3f = NULL;
7696                 ent->animcache_tvector3f = NULL;
7697                 ent->animcache_vertexposition = NULL;
7698                 ent->animcache_vertexmesh = NULL;
7699                 ent->animcache_vertexpositionbuffer = NULL;
7700                 ent->animcache_vertexmeshbuffer = NULL;
7701         }
7702 }
7703
7704 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7705 {
7706         int i;
7707
7708         // identical memory layout, so no need to allocate...
7709         // this also provides the vertexposition structure to everything, e.g.
7710         // depth masked rendering currently uses it even if having separate
7711         // arrays
7712         // NOTE: get rid of this optimization if changing it to e.g. 4f
7713         ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7714
7715         // TODO:
7716         // get rid of following uses of VERTEXPOSITION, change to the array:
7717         // R_DrawTextureSurfaceList_Sky if skyrendermasked
7718         // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7719         // R_DrawTextureSurfaceList_DepthOnly
7720         // R_Q1BSP_DrawShadowMap
7721
7722         switch(vid.renderpath)
7723         {
7724         case RENDERPATH_GL20:
7725         case RENDERPATH_CGGL:
7726                 // need the meshbuffers if !gl_mesh_separatearrays.integer
7727                 if (gl_mesh_separatearrays.integer)
7728                         return;
7729                 break;
7730         case RENDERPATH_D3D9:
7731         case RENDERPATH_D3D10:
7732         case RENDERPATH_D3D11:
7733                 // always need the meshbuffers
7734                 break;
7735         case RENDERPATH_GL13:
7736         case RENDERPATH_GL11:
7737                 // never need the meshbuffers
7738                 return;
7739         }
7740
7741         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7742                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7743         /*
7744         if (!ent->animcache_vertexposition)
7745                 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7746         */
7747         if (ent->animcache_vertexposition)
7748         {
7749                 /*
7750                 for (i = 0;i < numvertices;i++)
7751                         memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7752                 */
7753                 // TODO: upload vertex buffer?
7754         }
7755         if (ent->animcache_vertexmesh)
7756         {
7757                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7758                 for (i = 0;i < numvertices;i++)
7759                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7760                 if (ent->animcache_svector3f)
7761                         for (i = 0;i < numvertices;i++)
7762                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7763                 if (ent->animcache_tvector3f)
7764                         for (i = 0;i < numvertices;i++)
7765                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7766                 if (ent->animcache_normal3f)
7767                         for (i = 0;i < numvertices;i++)
7768                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7769                 // TODO: upload vertex buffer?
7770         }
7771 }
7772
7773 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7774 {
7775         dp_model_t *model = ent->model;
7776         int numvertices;
7777         // see if it's already cached this frame
7778         if (ent->animcache_vertex3f)
7779         {
7780                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7781                 if (wantnormals || wanttangents)
7782                 {
7783                         if (ent->animcache_normal3f)
7784                                 wantnormals = false;
7785                         if (ent->animcache_svector3f)
7786                                 wanttangents = false;
7787                         if (wantnormals || wanttangents)
7788                         {
7789                                 numvertices = model->surfmesh.num_vertices;
7790                                 if (wantnormals)
7791                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7792                                 if (wanttangents)
7793                                 {
7794                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7795                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7796                                 }
7797                                 if (!r_framedata_failed)
7798                                 {
7799                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7800                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7801                                 }
7802                         }
7803                 }
7804         }
7805         else
7806         {
7807                 // see if this ent is worth caching
7808                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7809                         return false;
7810                 // get some memory for this entity and generate mesh data
7811                 numvertices = model->surfmesh.num_vertices;
7812                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7813                 if (wantnormals)
7814                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7815                 if (wanttangents)
7816                 {
7817                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7818                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7819                 }
7820                 if (!r_framedata_failed)
7821                 {
7822                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7823                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7824                 }
7825         }
7826         return !r_framedata_failed;
7827 }
7828
7829 void R_AnimCache_CacheVisibleEntities(void)
7830 {
7831         int i;
7832         qboolean wantnormals = true;
7833         qboolean wanttangents = !r_showsurfaces.integer;
7834
7835         switch(vid.renderpath)
7836         {
7837         case RENDERPATH_GL20:
7838         case RENDERPATH_CGGL:
7839         case RENDERPATH_D3D9:
7840         case RENDERPATH_D3D10:
7841         case RENDERPATH_D3D11:
7842                 break;
7843         case RENDERPATH_GL13:
7844         case RENDERPATH_GL11:
7845                 wanttangents = false;
7846                 break;
7847         }
7848
7849         if (r_shownormals.integer)
7850                 wanttangents = wantnormals = true;
7851
7852         // TODO: thread this
7853         // NOTE: R_PrepareRTLights() also caches entities
7854
7855         for (i = 0;i < r_refdef.scene.numentities;i++)
7856                 if (r_refdef.viewcache.entityvisible[i])
7857                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7858 }
7859
7860 //==================================================================================
7861
7862 static void R_View_UpdateEntityLighting (void)
7863 {
7864         int i;
7865         entity_render_t *ent;
7866         vec3_t tempdiffusenormal, avg;
7867         vec_t f, fa, fd, fdd;
7868         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7869
7870         for (i = 0;i < r_refdef.scene.numentities;i++)
7871         {
7872                 ent = r_refdef.scene.entities[i];
7873
7874                 // skip unseen models
7875                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7876                         continue;
7877
7878                 // skip bsp models
7879                 if (ent->model && ent->model->brush.num_leafs)
7880                 {
7881                         // TODO: use modellight for r_ambient settings on world?
7882                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7883                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7884                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7885                         continue;
7886                 }
7887
7888                 // fetch the lighting from the worldmodel data
7889                 VectorClear(ent->modellight_ambient);
7890                 VectorClear(ent->modellight_diffuse);
7891                 VectorClear(tempdiffusenormal);
7892                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7893                 {
7894                         vec3_t org;
7895                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7896
7897                         // complete lightning for lit sprites
7898                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7899                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7900                         {
7901                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7902                                         org[2] = org[2] + r_overheadsprites_pushback.value;
7903                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, true, true);
7904                         }
7905                         else
7906                                 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7907
7908                         if(ent->flags & RENDER_EQUALIZE)
7909                         {
7910                                 // first fix up ambient lighting...
7911                                 if(r_equalize_entities_minambient.value > 0)
7912                                 {
7913                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7914                                         if(fd > 0)
7915                                         {
7916                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7917                                                 if(fa < r_equalize_entities_minambient.value * fd)
7918                                                 {
7919                                                         // solve:
7920                                                         //   fa'/fd' = minambient
7921                                                         //   fa'+0.25*fd' = fa+0.25*fd
7922                                                         //   ...
7923                                                         //   fa' = fd' * minambient
7924                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7925                                                         //   ...
7926                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7927                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7928                                                         //   ...
7929                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7930                                                         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
7931                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7932                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7933                                                 }
7934                                         }
7935                                 }
7936
7937                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7938                                 {
7939                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7940                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7941                                         if(f > 0)
7942                                         {
7943                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7944                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7945                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7946                                         }
7947                                 }
7948                         }
7949                 }
7950                 else // highly rare
7951                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7952
7953                 // move the light direction into modelspace coordinates for lighting code
7954                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7955                 if(VectorLength2(ent->modellight_lightdir) == 0)
7956                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7957                 VectorNormalize(ent->modellight_lightdir);
7958         }
7959 }
7960
7961 #define MAX_LINEOFSIGHTTRACES 64
7962
7963 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7964 {
7965         int i;
7966         vec3_t boxmins, boxmaxs;
7967         vec3_t start;
7968         vec3_t end;
7969         dp_model_t *model = r_refdef.scene.worldmodel;
7970
7971         if (!model || !model->brush.TraceLineOfSight)
7972                 return true;
7973
7974         // expand the box a little
7975         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7976         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7977         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7978         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7979         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7980         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7981
7982         // return true if eye is inside enlarged box
7983         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7984                 return true;
7985
7986         // try center
7987         VectorCopy(eye, start);
7988         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7989         if (model->brush.TraceLineOfSight(model, start, end))
7990                 return true;
7991
7992         // try various random positions
7993         for (i = 0;i < numsamples;i++)
7994         {
7995                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7996                 if (model->brush.TraceLineOfSight(model, start, end))
7997                         return true;
7998         }
7999
8000         return false;
8001 }
8002
8003
8004 static void R_View_UpdateEntityVisible (void)
8005 {
8006         int i;
8007         int renderimask;
8008         int samples;
8009         entity_render_t *ent;
8010
8011         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8012                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8013                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
8014                 :                                                          RENDER_EXTERIORMODEL;
8015         if (!r_drawviewmodel.integer)
8016                 renderimask |= RENDER_VIEWMODEL;
8017         if (!r_drawexteriormodel.integer)
8018                 renderimask |= RENDER_EXTERIORMODEL;
8019         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8020         {
8021                 // worldmodel can check visibility
8022                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8023                 for (i = 0;i < r_refdef.scene.numentities;i++)
8024                 {
8025                         ent = r_refdef.scene.entities[i];
8026                         if (!(ent->flags & renderimask))
8027                         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)))
8028                         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))
8029                                 r_refdef.viewcache.entityvisible[i] = true;
8030                 }
8031                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8032                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8033                 {
8034                         for (i = 0;i < r_refdef.scene.numentities;i++)
8035                         {
8036                                 ent = r_refdef.scene.entities[i];
8037                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8038                                 {
8039                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8040                                         if (samples < 0)
8041                                                 continue; // temp entities do pvs only
8042                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8043                                                 ent->last_trace_visibility = realtime;
8044                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8045                                                 r_refdef.viewcache.entityvisible[i] = 0;
8046                                 }
8047                         }
8048                 }
8049         }
8050         else
8051         {
8052                 // no worldmodel or it can't check visibility
8053                 for (i = 0;i < r_refdef.scene.numentities;i++)
8054                 {
8055                         ent = r_refdef.scene.entities[i];
8056                         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));
8057                 }
8058         }
8059 }
8060
8061 /// only used if skyrendermasked, and normally returns false
8062 int R_DrawBrushModelsSky (void)
8063 {
8064         int i, sky;
8065         entity_render_t *ent;
8066
8067         sky = false;
8068         for (i = 0;i < r_refdef.scene.numentities;i++)
8069         {
8070                 if (!r_refdef.viewcache.entityvisible[i])
8071                         continue;
8072                 ent = r_refdef.scene.entities[i];
8073                 if (!ent->model || !ent->model->DrawSky)
8074                         continue;
8075                 ent->model->DrawSky(ent);
8076                 sky = true;
8077         }
8078         return sky;
8079 }
8080
8081 static void R_DrawNoModel(entity_render_t *ent);
8082 static void R_DrawModels(void)
8083 {
8084         int i;
8085         entity_render_t *ent;
8086
8087         for (i = 0;i < r_refdef.scene.numentities;i++)
8088         {
8089                 if (!r_refdef.viewcache.entityvisible[i])
8090                         continue;
8091                 ent = r_refdef.scene.entities[i];
8092                 r_refdef.stats.entities++;
8093                 if (ent->model && ent->model->Draw != NULL)
8094                         ent->model->Draw(ent);
8095                 else
8096                         R_DrawNoModel(ent);
8097         }
8098 }
8099
8100 static void R_DrawModelsDepth(void)
8101 {
8102         int i;
8103         entity_render_t *ent;
8104
8105         for (i = 0;i < r_refdef.scene.numentities;i++)
8106         {
8107                 if (!r_refdef.viewcache.entityvisible[i])
8108                         continue;
8109                 ent = r_refdef.scene.entities[i];
8110                 if (ent->model && ent->model->DrawDepth != NULL)
8111                         ent->model->DrawDepth(ent);
8112         }
8113 }
8114
8115 static void R_DrawModelsDebug(void)
8116 {
8117         int i;
8118         entity_render_t *ent;
8119
8120         for (i = 0;i < r_refdef.scene.numentities;i++)
8121         {
8122                 if (!r_refdef.viewcache.entityvisible[i])
8123                         continue;
8124                 ent = r_refdef.scene.entities[i];
8125                 if (ent->model && ent->model->DrawDebug != NULL)
8126                         ent->model->DrawDebug(ent);
8127         }
8128 }
8129
8130 static void R_DrawModelsAddWaterPlanes(void)
8131 {
8132         int i;
8133         entity_render_t *ent;
8134
8135         for (i = 0;i < r_refdef.scene.numentities;i++)
8136         {
8137                 if (!r_refdef.viewcache.entityvisible[i])
8138                         continue;
8139                 ent = r_refdef.scene.entities[i];
8140                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8141                         ent->model->DrawAddWaterPlanes(ent);
8142         }
8143 }
8144
8145 static void R_View_SetFrustum(const int *scissor)
8146 {
8147         int i;
8148         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8149         vec3_t forward, left, up, origin, v;
8150
8151         if(scissor)
8152         {
8153                 // flipped x coordinates (because x points left here)
8154                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8155                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8156
8157                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8158                 switch(vid.renderpath)
8159                 {
8160                         case RENDERPATH_D3D9:
8161                         case RENDERPATH_D3D10:
8162                         case RENDERPATH_D3D11:
8163                                 // non-flipped y coordinates
8164                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8165                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8166                                 break;
8167                         case RENDERPATH_GL11:
8168                         case RENDERPATH_GL13:
8169                         case RENDERPATH_GL20:
8170                         case RENDERPATH_CGGL:
8171                                 // non-flipped y coordinates
8172                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8173                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8174                                 break;
8175                 }
8176         }
8177
8178         // we can't trust r_refdef.view.forward and friends in reflected scenes
8179         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8180
8181 #if 0
8182         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8183         r_refdef.view.frustum[0].normal[1] = 0 - 0;
8184         r_refdef.view.frustum[0].normal[2] = -1 - 0;
8185         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8186         r_refdef.view.frustum[1].normal[1] = 0 + 0;
8187         r_refdef.view.frustum[1].normal[2] = -1 + 0;
8188         r_refdef.view.frustum[2].normal[0] = 0 - 0;
8189         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8190         r_refdef.view.frustum[2].normal[2] = -1 - 0;
8191         r_refdef.view.frustum[3].normal[0] = 0 + 0;
8192         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8193         r_refdef.view.frustum[3].normal[2] = -1 + 0;
8194 #endif
8195
8196 #if 0
8197         zNear = r_refdef.nearclip;
8198         nudge = 1.0 - 1.0 / (1<<23);
8199         r_refdef.view.frustum[4].normal[0] = 0 - 0;
8200         r_refdef.view.frustum[4].normal[1] = 0 - 0;
8201         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8202         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8203         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8204         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8205         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8206         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8207 #endif
8208
8209
8210
8211 #if 0
8212         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8213         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8214         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8215         r_refdef.view.frustum[0].dist = m[15] - m[12];
8216
8217         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8218         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8219         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8220         r_refdef.view.frustum[1].dist = m[15] + m[12];
8221
8222         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8223         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8224         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8225         r_refdef.view.frustum[2].dist = m[15] - m[13];
8226
8227         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8228         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8229         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8230         r_refdef.view.frustum[3].dist = m[15] + m[13];
8231
8232         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8233         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8234         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8235         r_refdef.view.frustum[4].dist = m[15] - m[14];
8236
8237         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8238         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8239         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8240         r_refdef.view.frustum[5].dist = m[15] + m[14];
8241 #endif
8242
8243         if (r_refdef.view.useperspective)
8244         {
8245                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8246                 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]);
8247                 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]);
8248                 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]);
8249                 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]);
8250
8251                 // then the normals from the corners relative to origin
8252                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8253                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8254                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8255                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8256
8257                 // in a NORMAL view, forward cross left == up
8258                 // in a REFLECTED view, forward cross left == down
8259                 // so our cross products above need to be adjusted for a left handed coordinate system
8260                 CrossProduct(forward, left, v);
8261                 if(DotProduct(v, up) < 0)
8262                 {
8263                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8264                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8265                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8266                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8267                 }
8268
8269                 // Leaving those out was a mistake, those were in the old code, and they
8270                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8271                 // I couldn't reproduce it after adding those normalizations. --blub
8272                 VectorNormalize(r_refdef.view.frustum[0].normal);
8273                 VectorNormalize(r_refdef.view.frustum[1].normal);
8274                 VectorNormalize(r_refdef.view.frustum[2].normal);
8275                 VectorNormalize(r_refdef.view.frustum[3].normal);
8276
8277                 // make the corners absolute
8278                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8279                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8280                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8281                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8282
8283                 // one more normal
8284                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8285
8286                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8287                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8288                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8289                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8290                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8291         }
8292         else
8293         {
8294                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8295                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8296                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8297                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8298                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8299                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8300                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8301                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8302                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8303                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8304         }
8305         r_refdef.view.numfrustumplanes = 5;
8306
8307         if (r_refdef.view.useclipplane)
8308         {
8309                 r_refdef.view.numfrustumplanes = 6;
8310                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8311         }
8312
8313         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8314                 PlaneClassify(r_refdef.view.frustum + i);
8315
8316         // LordHavoc: note to all quake engine coders, Quake had a special case
8317         // for 90 degrees which assumed a square view (wrong), so I removed it,
8318         // Quake2 has it disabled as well.
8319
8320         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8321         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8322         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8323         //PlaneClassify(&frustum[0]);
8324
8325         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8326         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8327         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8328         //PlaneClassify(&frustum[1]);
8329
8330         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8331         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8332         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8333         //PlaneClassify(&frustum[2]);
8334
8335         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8336         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8337         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8338         //PlaneClassify(&frustum[3]);
8339
8340         // nearclip plane
8341         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8342         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8343         //PlaneClassify(&frustum[4]);
8344 }
8345
8346 void R_View_UpdateWithScissor(const int *myscissor)
8347 {
8348         R_Main_ResizeViewCache();
8349         R_View_SetFrustum(myscissor);
8350         R_View_WorldVisibility(r_refdef.view.useclipplane);
8351         R_View_UpdateEntityVisible();
8352         R_View_UpdateEntityLighting();
8353 }
8354
8355 void R_View_Update(void)
8356 {
8357         R_Main_ResizeViewCache();
8358         R_View_SetFrustum(NULL);
8359         R_View_WorldVisibility(r_refdef.view.useclipplane);
8360         R_View_UpdateEntityVisible();
8361         R_View_UpdateEntityLighting();
8362 }
8363
8364 void R_SetupView(qboolean allowwaterclippingplane)
8365 {
8366         const float *customclipplane = NULL;
8367         float plane[4];
8368         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8369         {
8370                 // LordHavoc: couldn't figure out how to make this approach the
8371                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8372                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8373                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8374                         dist = r_refdef.view.clipplane.dist;
8375                 plane[0] = r_refdef.view.clipplane.normal[0];
8376                 plane[1] = r_refdef.view.clipplane.normal[1];
8377                 plane[2] = r_refdef.view.clipplane.normal[2];
8378                 plane[3] = dist;
8379                 customclipplane = plane;
8380         }
8381
8382         if (!r_refdef.view.useperspective)
8383                 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);
8384         else if (vid.stencil && r_useinfinitefarclip.integer)
8385                 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);
8386         else
8387                 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);
8388         R_SetViewport(&r_refdef.view.viewport);
8389 }
8390
8391 void R_EntityMatrix(const matrix4x4_t *matrix)
8392 {
8393         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8394         {
8395                 gl_modelmatrixchanged = false;
8396                 gl_modelmatrix = *matrix;
8397                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8398                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8399                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8400                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8401                 CHECKGLERROR
8402                 switch(vid.renderpath)
8403                 {
8404                 case RENDERPATH_D3D9:
8405 #ifdef SUPPORTD3D
8406                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8407                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8408 #endif
8409                         break;
8410                 case RENDERPATH_D3D10:
8411                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8412                         break;
8413                 case RENDERPATH_D3D11:
8414                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8415                         break;
8416                 case RENDERPATH_GL20:
8417                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8418                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8419                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8420                         break;
8421                 case RENDERPATH_CGGL:
8422 #ifdef SUPPORTCG
8423                         CHECKCGERROR
8424                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8425                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8426                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8427 #endif
8428                         break;
8429                 case RENDERPATH_GL13:
8430                 case RENDERPATH_GL11:
8431                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8432                         break;
8433                 }
8434         }
8435 }
8436
8437 void R_ResetViewRendering2D(void)
8438 {
8439         r_viewport_t viewport;
8440         DrawQ_Finish();
8441
8442         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8443         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);
8444         R_SetViewport(&viewport);
8445         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8446         GL_Color(1, 1, 1, 1);
8447         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8448         GL_BlendFunc(GL_ONE, GL_ZERO);
8449         GL_AlphaTest(false);
8450         GL_ScissorTest(false);
8451         GL_DepthMask(false);
8452         GL_DepthRange(0, 1);
8453         GL_DepthTest(false);
8454         GL_DepthFunc(GL_LEQUAL);
8455         R_EntityMatrix(&identitymatrix);
8456         R_Mesh_ResetTextureState();
8457         GL_PolygonOffset(0, 0);
8458         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8459         switch(vid.renderpath)
8460         {
8461         case RENDERPATH_GL11:
8462         case RENDERPATH_GL13:
8463         case RENDERPATH_GL20:
8464         case RENDERPATH_CGGL:
8465                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8466                 break;
8467         case RENDERPATH_D3D9:
8468         case RENDERPATH_D3D10:
8469         case RENDERPATH_D3D11:
8470                 break;
8471         }
8472         GL_CullFace(GL_NONE);
8473 }
8474
8475 void R_ResetViewRendering3D(void)
8476 {
8477         DrawQ_Finish();
8478
8479         R_SetupView(true);
8480         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8481         GL_Color(1, 1, 1, 1);
8482         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8483         GL_BlendFunc(GL_ONE, GL_ZERO);
8484         GL_AlphaTest(false);
8485         GL_ScissorTest(true);
8486         GL_DepthMask(true);
8487         GL_DepthRange(0, 1);
8488         GL_DepthTest(true);
8489         GL_DepthFunc(GL_LEQUAL);
8490         R_EntityMatrix(&identitymatrix);
8491         R_Mesh_ResetTextureState();
8492         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8493         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8494         switch(vid.renderpath)
8495         {
8496         case RENDERPATH_GL11:
8497         case RENDERPATH_GL13:
8498         case RENDERPATH_GL20:
8499         case RENDERPATH_CGGL:
8500                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8501                 break;
8502         case RENDERPATH_D3D9:
8503         case RENDERPATH_D3D10:
8504         case RENDERPATH_D3D11:
8505                 break;
8506         }
8507         GL_CullFace(r_refdef.view.cullface_back);
8508 }
8509
8510 /*
8511 ================
8512 R_RenderView_UpdateViewVectors
8513 ================
8514 */
8515 static void R_RenderView_UpdateViewVectors(void)
8516 {
8517         // break apart the view matrix into vectors for various purposes
8518         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8519         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8520         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8521         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8522         // make an inverted copy of the view matrix for tracking sprites
8523         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8524 }
8525
8526 void R_RenderScene(void);
8527 void R_RenderWaterPlanes(void);
8528
8529 static void R_Water_StartFrame(void)
8530 {
8531         int i;
8532         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8533         r_waterstate_waterplane_t *p;
8534
8535         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8536                 return;
8537
8538         switch(vid.renderpath)
8539         {
8540         case RENDERPATH_GL20:
8541         case RENDERPATH_CGGL:
8542         case RENDERPATH_D3D9:
8543         case RENDERPATH_D3D10:
8544         case RENDERPATH_D3D11:
8545                 break;
8546         case RENDERPATH_GL13:
8547         case RENDERPATH_GL11:
8548                 return;
8549         }
8550
8551         // set waterwidth and waterheight to the water resolution that will be
8552         // used (often less than the screen resolution for faster rendering)
8553         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8554         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8555
8556         // calculate desired texture sizes
8557         // can't use water if the card does not support the texture size
8558         if (!r_water.integer || r_showsurfaces.integer)
8559                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8560         else if (vid.support.arb_texture_non_power_of_two)
8561         {
8562                 texturewidth = waterwidth;
8563                 textureheight = waterheight;
8564                 camerawidth = waterwidth;
8565                 cameraheight = waterheight;
8566         }
8567         else
8568         {
8569                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8570                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8571                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8572                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8573         }
8574
8575         // allocate textures as needed
8576         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8577         {
8578                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8579                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8580                 {
8581                         if (p->texture_refraction)
8582                                 R_FreeTexture(p->texture_refraction);
8583                         p->texture_refraction = NULL;
8584                         if (p->texture_reflection)
8585                                 R_FreeTexture(p->texture_reflection);
8586                         p->texture_reflection = NULL;
8587                         if (p->texture_camera)
8588                                 R_FreeTexture(p->texture_camera);
8589                         p->texture_camera = NULL;
8590                 }
8591                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8592                 r_waterstate.texturewidth = texturewidth;
8593                 r_waterstate.textureheight = textureheight;
8594                 r_waterstate.camerawidth = camerawidth;
8595                 r_waterstate.cameraheight = cameraheight;
8596         }
8597
8598         if (r_waterstate.texturewidth)
8599         {
8600                 r_waterstate.enabled = true;
8601
8602                 // when doing a reduced render (HDR) we want to use a smaller area
8603                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8604                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8605
8606                 // set up variables that will be used in shader setup
8607                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8608                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8609                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8610                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8611         }
8612
8613         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8614         r_waterstate.numwaterplanes = 0;
8615 }
8616
8617 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8618 {
8619         int triangleindex, planeindex;
8620         const int *e;
8621         vec3_t vert[3];
8622         vec3_t normal;
8623         vec3_t center;
8624         mplane_t plane;
8625         r_waterstate_waterplane_t *p;
8626         texture_t *t = R_GetCurrentTexture(surface->texture);
8627
8628         // just use the first triangle with a valid normal for any decisions
8629         VectorClear(normal);
8630         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8631         {
8632                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8633                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8634                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8635                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8636                 if (VectorLength2(normal) >= 0.001)
8637                         break;
8638         }
8639
8640         VectorCopy(normal, plane.normal);
8641         VectorNormalize(plane.normal);
8642         plane.dist = DotProduct(vert[0], plane.normal);
8643         PlaneClassify(&plane);
8644         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8645         {
8646                 // skip backfaces (except if nocullface is set)
8647                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8648                         return;
8649                 VectorNegate(plane.normal, plane.normal);
8650                 plane.dist *= -1;
8651                 PlaneClassify(&plane);
8652         }
8653
8654
8655         // find a matching plane if there is one
8656         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8657                 if(p->camera_entity == t->camera_entity)
8658                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8659                                 break;
8660         if (planeindex >= r_waterstate.maxwaterplanes)
8661                 return; // nothing we can do, out of planes
8662
8663         // if this triangle does not fit any known plane rendered this frame, add one
8664         if (planeindex >= r_waterstate.numwaterplanes)
8665         {
8666                 // store the new plane
8667                 r_waterstate.numwaterplanes++;
8668                 p->plane = plane;
8669                 // clear materialflags and pvs
8670                 p->materialflags = 0;
8671                 p->pvsvalid = false;
8672                 p->camera_entity = t->camera_entity;
8673                 VectorCopy(surface->mins, p->mins);
8674                 VectorCopy(surface->maxs, p->maxs);
8675         }
8676         else
8677         {
8678                 // merge mins/maxs
8679                 p->mins[0] = min(p->mins[0], surface->mins[0]);
8680                 p->mins[1] = min(p->mins[1], surface->mins[1]);
8681                 p->mins[2] = min(p->mins[2], surface->mins[2]);
8682                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8683                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8684                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8685         }
8686         // merge this surface's materialflags into the waterplane
8687         p->materialflags |= t->currentmaterialflags;
8688         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8689         {
8690                 // merge this surface's PVS into the waterplane
8691                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8692                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8693                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8694                 {
8695                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8696                         p->pvsvalid = true;
8697                 }
8698         }
8699 }
8700
8701 static void R_Water_ProcessPlanes(void)
8702 {
8703         int myscissor[4];
8704         r_refdef_view_t originalview;
8705         r_refdef_view_t myview;
8706         int planeindex;
8707         r_waterstate_waterplane_t *p;
8708         vec3_t visorigin;
8709
8710         originalview = r_refdef.view;
8711
8712         // make sure enough textures are allocated
8713         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8714         {
8715                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8716                 {
8717                         if (!p->texture_refraction)
8718                                 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);
8719                         if (!p->texture_refraction)
8720                                 goto error;
8721                 }
8722                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8723                 {
8724                         if (!p->texture_camera)
8725                                 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);
8726                         if (!p->texture_camera)
8727                                 goto error;
8728                 }
8729
8730                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8731                 {
8732                         if (!p->texture_reflection)
8733                                 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);
8734                         if (!p->texture_reflection)
8735                                 goto error;
8736                 }
8737         }
8738
8739         // render views
8740         r_refdef.view = originalview;
8741         r_refdef.view.showdebug = false;
8742         r_refdef.view.width = r_waterstate.waterwidth;
8743         r_refdef.view.height = r_waterstate.waterheight;
8744         r_refdef.view.useclipplane = true;
8745         myview = r_refdef.view;
8746         r_waterstate.renderingscene = true;
8747         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8748         {
8749                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8750                 {
8751                         r_refdef.view = myview;
8752                         if(r_water_scissormode.integer)
8753                         {
8754                                 R_SetupView(true);
8755                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8756                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8757                         }
8758
8759                         // render reflected scene and copy into texture
8760                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8761                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8762                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8763                         r_refdef.view.clipplane = p->plane;
8764
8765                         // reverse the cullface settings for this render
8766                         r_refdef.view.cullface_front = GL_FRONT;
8767                         r_refdef.view.cullface_back = GL_BACK;
8768                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8769                         {
8770                                 r_refdef.view.usecustompvs = true;
8771                                 if (p->pvsvalid)
8772                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8773                                 else
8774                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8775                         }
8776
8777                         R_ResetViewRendering3D();
8778                         R_ClearScreen(r_refdef.fogenabled);
8779                         if(r_water_scissormode.integer & 2)
8780                                 R_View_UpdateWithScissor(myscissor);
8781                         else
8782                                 R_View_Update();
8783                         if(r_water_scissormode.integer & 1)
8784                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8785                         R_RenderScene();
8786
8787                         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);
8788                 }
8789
8790                 // render the normal view scene and copy into texture
8791                 // (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)
8792                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8793                 {
8794                         r_refdef.view = myview;
8795                         if(r_water_scissormode.integer)
8796                         {
8797                                 R_SetupView(true);
8798                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8799                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8800                         }
8801
8802                         r_waterstate.renderingrefraction = true;
8803
8804                         r_refdef.view.clipplane = p->plane;
8805                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8806                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8807
8808                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8809                         {
8810                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8811                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8812                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8813                                 R_RenderView_UpdateViewVectors();
8814                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8815                                 {
8816                                         r_refdef.view.usecustompvs = true;
8817                                         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);
8818                                 }
8819                         }
8820
8821                         PlaneClassify(&r_refdef.view.clipplane);
8822
8823                         R_ResetViewRendering3D();
8824                         R_ClearScreen(r_refdef.fogenabled);
8825                         if(r_water_scissormode.integer & 2)
8826                                 R_View_UpdateWithScissor(myscissor);
8827                         else
8828                                 R_View_Update();
8829                         if(r_water_scissormode.integer & 1)
8830                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8831                         R_RenderScene();
8832
8833                         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);
8834                         r_waterstate.renderingrefraction = false;
8835                 }
8836                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8837                 {
8838                         r_refdef.view = myview;
8839
8840                         r_refdef.view.clipplane = p->plane;
8841                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8842                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8843
8844                         r_refdef.view.width = r_waterstate.camerawidth;
8845                         r_refdef.view.height = r_waterstate.cameraheight;
8846                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8847                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8848
8849                         if(p->camera_entity)
8850                         {
8851                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8852                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8853                         }
8854
8855                         // note: all of the view is used for displaying... so
8856                         // there is no use in scissoring
8857
8858                         // reverse the cullface settings for this render
8859                         r_refdef.view.cullface_front = GL_FRONT;
8860                         r_refdef.view.cullface_back = GL_BACK;
8861                         // also reverse the view matrix
8862                         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
8863                         R_RenderView_UpdateViewVectors();
8864                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8865                         {
8866                                 r_refdef.view.usecustompvs = true;
8867                                 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);
8868                         }
8869                         
8870                         // camera needs no clipplane
8871                         r_refdef.view.useclipplane = false;
8872
8873                         PlaneClassify(&r_refdef.view.clipplane);
8874
8875                         R_ResetViewRendering3D();
8876                         R_ClearScreen(r_refdef.fogenabled);
8877                         R_View_Update();
8878                         R_RenderScene();
8879
8880                         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);
8881                         r_waterstate.renderingrefraction = false;
8882                 }
8883
8884         }
8885         r_waterstate.renderingscene = false;
8886         r_refdef.view = originalview;
8887         R_ResetViewRendering3D();
8888         R_ClearScreen(r_refdef.fogenabled);
8889         R_View_Update();
8890         return;
8891 error:
8892         r_refdef.view = originalview;
8893         r_waterstate.renderingscene = false;
8894         Cvar_SetValueQuick(&r_water, 0);
8895         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8896         return;
8897 }
8898
8899 void R_Bloom_StartFrame(void)
8900 {
8901         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8902
8903         switch(vid.renderpath)
8904         {
8905         case RENDERPATH_GL20:
8906         case RENDERPATH_CGGL:
8907         case RENDERPATH_D3D9:
8908         case RENDERPATH_D3D10:
8909         case RENDERPATH_D3D11:
8910                 break;
8911         case RENDERPATH_GL13:
8912         case RENDERPATH_GL11:
8913                 return;
8914         }
8915
8916         // set bloomwidth and bloomheight to the bloom resolution that will be
8917         // used (often less than the screen resolution for faster rendering)
8918         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8919         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8920         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8921         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8922         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8923
8924         // calculate desired texture sizes
8925         if (vid.support.arb_texture_non_power_of_two)
8926         {
8927                 screentexturewidth = r_refdef.view.width;
8928                 screentextureheight = r_refdef.view.height;
8929                 bloomtexturewidth = r_bloomstate.bloomwidth;
8930                 bloomtextureheight = r_bloomstate.bloomheight;
8931         }
8932         else
8933         {
8934                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8935                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8936                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8937                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8938         }
8939
8940         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))
8941         {
8942                 Cvar_SetValueQuick(&r_hdr, 0);
8943                 Cvar_SetValueQuick(&r_bloom, 0);
8944                 Cvar_SetValueQuick(&r_motionblur, 0);
8945                 Cvar_SetValueQuick(&r_damageblur, 0);
8946         }
8947
8948         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)))
8949                 screentexturewidth = screentextureheight = 0;
8950         if (!r_hdr.integer && !r_bloom.integer)
8951                 bloomtexturewidth = bloomtextureheight = 0;
8952
8953         // allocate textures as needed
8954         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8955         {
8956                 if (r_bloomstate.texture_screen)
8957                         R_FreeTexture(r_bloomstate.texture_screen);
8958                 r_bloomstate.texture_screen = NULL;
8959                 r_bloomstate.screentexturewidth = screentexturewidth;
8960                 r_bloomstate.screentextureheight = screentextureheight;
8961                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8962                         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);
8963         }
8964         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8965         {
8966                 if (r_bloomstate.texture_bloom)
8967                         R_FreeTexture(r_bloomstate.texture_bloom);
8968                 r_bloomstate.texture_bloom = NULL;
8969                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8970                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8971                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8972                         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);
8973         }
8974
8975         // when doing a reduced render (HDR) we want to use a smaller area
8976         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8977         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8978         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8979         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8980         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8981
8982         // set up a texcoord array for the full resolution screen image
8983         // (we have to keep this around to copy back during final render)
8984         r_bloomstate.screentexcoord2f[0] = 0;
8985         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8986         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8987         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8988         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8989         r_bloomstate.screentexcoord2f[5] = 0;
8990         r_bloomstate.screentexcoord2f[6] = 0;
8991         r_bloomstate.screentexcoord2f[7] = 0;
8992
8993         // set up a texcoord array for the reduced resolution bloom image
8994         // (which will be additive blended over the screen image)
8995         r_bloomstate.bloomtexcoord2f[0] = 0;
8996         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8997         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8998         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8999         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9000         r_bloomstate.bloomtexcoord2f[5] = 0;
9001         r_bloomstate.bloomtexcoord2f[6] = 0;
9002         r_bloomstate.bloomtexcoord2f[7] = 0;
9003
9004         switch(vid.renderpath)
9005         {
9006         case RENDERPATH_GL11:
9007         case RENDERPATH_GL13:
9008         case RENDERPATH_GL20:
9009         case RENDERPATH_CGGL:
9010                 break;
9011         case RENDERPATH_D3D9:
9012         case RENDERPATH_D3D10:
9013         case RENDERPATH_D3D11:
9014                 {
9015                         int i;
9016                         for (i = 0;i < 4;i++)
9017                         {
9018                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
9019                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
9020                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
9021                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
9022                         }
9023                 }
9024                 break;
9025         }
9026
9027         if (r_hdr.integer || r_bloom.integer)
9028         {
9029                 r_bloomstate.enabled = true;
9030                 r_bloomstate.hdr = r_hdr.integer != 0;
9031         }
9032
9033         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);
9034 }
9035
9036 void R_Bloom_CopyBloomTexture(float colorscale)
9037 {
9038         r_refdef.stats.bloom++;
9039
9040         // scale down screen texture to the bloom texture size
9041         CHECKGLERROR
9042         R_SetViewport(&r_bloomstate.viewport);
9043         GL_BlendFunc(GL_ONE, GL_ZERO);
9044         GL_Color(colorscale, colorscale, colorscale, 1);
9045         // 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...
9046         switch(vid.renderpath)
9047         {
9048         case RENDERPATH_GL11:
9049         case RENDERPATH_GL13:
9050         case RENDERPATH_GL20:
9051         case RENDERPATH_CGGL:
9052                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9053                 break;
9054         case RENDERPATH_D3D9:
9055         case RENDERPATH_D3D10:
9056         case RENDERPATH_D3D11:
9057                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9058                 break;
9059         }
9060         // TODO: do boxfilter scale-down in shader?
9061         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9062         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9063         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9064
9065         // we now have a bloom image in the framebuffer
9066         // copy it into the bloom image texture for later processing
9067         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);
9068         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9069 }
9070
9071 void R_Bloom_CopyHDRTexture(void)
9072 {
9073         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);
9074         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9075 }
9076
9077 void R_Bloom_MakeTexture(void)
9078 {
9079         int x, range, dir;
9080         float xoffset, yoffset, r, brighten;
9081
9082         r_refdef.stats.bloom++;
9083
9084         R_ResetViewRendering2D();
9085
9086         // we have a bloom image in the framebuffer
9087         CHECKGLERROR
9088         R_SetViewport(&r_bloomstate.viewport);
9089
9090         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9091         {
9092                 x *= 2;
9093                 r = bound(0, r_bloom_colorexponent.value / x, 1);
9094                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9095                 GL_Color(r,r,r,1);
9096                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9097                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9098                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9099                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9100
9101                 // copy the vertically blurred bloom view to a texture
9102                 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);
9103                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9104         }
9105
9106         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9107         brighten = r_bloom_brighten.value;
9108         if (r_hdr.integer)
9109                 brighten *= r_hdr_range.value;
9110         brighten = sqrt(brighten);
9111         if(range >= 1)
9112                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9113         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9114
9115         for (dir = 0;dir < 2;dir++)
9116         {
9117                 // blend on at multiple vertical offsets to achieve a vertical blur
9118                 // TODO: do offset blends using GLSL
9119                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9120                 GL_BlendFunc(GL_ONE, GL_ZERO);
9121                 for (x = -range;x <= range;x++)
9122                 {
9123                         if (!dir){xoffset = 0;yoffset = x;}
9124                         else {xoffset = x;yoffset = 0;}
9125                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
9126                         yoffset /= (float)r_bloomstate.bloomtextureheight;
9127                         // compute a texcoord array with the specified x and y offset
9128                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9129                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9130                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9131                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9132                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9133                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9134                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9135                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9136                         // this r value looks like a 'dot' particle, fading sharply to
9137                         // black at the edges
9138                         // (probably not realistic but looks good enough)
9139                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9140                         //r = brighten/(range*2+1);
9141                         r = brighten / (range * 2 + 1);
9142                         if(range >= 1)
9143                                 r *= (1 - x*x/(float)(range*range));
9144                         GL_Color(r, r, r, 1);
9145                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9146                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9147                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9148                         GL_BlendFunc(GL_ONE, GL_ONE);
9149                 }
9150
9151                 // copy the vertically blurred bloom view to a texture
9152                 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);
9153                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9154         }
9155 }
9156
9157 void R_HDR_RenderBloomTexture(void)
9158 {
9159         int oldwidth, oldheight;
9160         float oldcolorscale;
9161
9162         oldcolorscale = r_refdef.view.colorscale;
9163         oldwidth = r_refdef.view.width;
9164         oldheight = r_refdef.view.height;
9165         r_refdef.view.width = r_bloomstate.bloomwidth;
9166         r_refdef.view.height = r_bloomstate.bloomheight;
9167
9168         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
9169         // TODO: add exposure compensation features
9170         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9171
9172         r_refdef.view.showdebug = false;
9173         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9174
9175         R_ResetViewRendering3D();
9176
9177         R_ClearScreen(r_refdef.fogenabled);
9178         if (r_timereport_active)
9179                 R_TimeReport("HDRclear");
9180
9181         R_View_Update();
9182         if (r_timereport_active)
9183                 R_TimeReport("visibility");
9184
9185         // only do secondary renders with HDR if r_hdr is 2 or higher
9186         r_waterstate.numwaterplanes = 0;
9187         if (r_waterstate.enabled && r_hdr.integer >= 2)
9188                 R_RenderWaterPlanes();
9189
9190         r_refdef.view.showdebug = true;
9191         R_RenderScene();
9192         r_waterstate.numwaterplanes = 0;
9193
9194         R_ResetViewRendering2D();
9195
9196         R_Bloom_CopyHDRTexture();
9197         R_Bloom_MakeTexture();
9198
9199         // restore the view settings
9200         r_refdef.view.width = oldwidth;
9201         r_refdef.view.height = oldheight;
9202         r_refdef.view.colorscale = oldcolorscale;
9203
9204         R_ResetViewRendering3D();
9205
9206         R_ClearScreen(r_refdef.fogenabled);
9207         if (r_timereport_active)
9208                 R_TimeReport("viewclear");
9209 }
9210
9211 static void R_BlendView(void)
9212 {
9213         unsigned int permutation;
9214         float uservecs[4][4];
9215
9216         switch (vid.renderpath)
9217         {
9218         case RENDERPATH_GL20:
9219         case RENDERPATH_CGGL:
9220         case RENDERPATH_D3D9:
9221         case RENDERPATH_D3D10:
9222         case RENDERPATH_D3D11:
9223                 permutation =
9224                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9225                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9226                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9227                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9228                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9229
9230                 if (r_bloomstate.texture_screen)
9231                 {
9232                         // make sure the buffer is available
9233                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9234
9235                         R_ResetViewRendering2D();
9236
9237                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9238                         {
9239                                 // declare variables
9240                                 float speed;
9241                                 static float avgspeed;
9242
9243                                 speed = VectorLength(cl.movement_velocity);
9244
9245                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9246                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9247
9248                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9249                                 speed = bound(0, speed, 1);
9250                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9251
9252                                 // calculate values into a standard alpha
9253                                 cl.motionbluralpha = 1 - exp(-
9254                                                 (
9255                                                  (r_motionblur.value * speed / 80)
9256                                                  +
9257                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9258                                                 )
9259                                                 /
9260                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
9261                                            );
9262
9263                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9264                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9265                                 // apply the blur
9266                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9267                                 {
9268                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9269                                         GL_Color(1, 1, 1, cl.motionbluralpha);
9270                                         switch(vid.renderpath)
9271                                         {
9272                                         case RENDERPATH_GL11:
9273                                         case RENDERPATH_GL13:
9274                                         case RENDERPATH_GL20:
9275                                         case RENDERPATH_CGGL:
9276                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9277                                                 break;
9278                                         case RENDERPATH_D3D9:
9279                                         case RENDERPATH_D3D10:
9280                                         case RENDERPATH_D3D11:
9281                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9282                                                 break;
9283                                         }
9284                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9285                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9286                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9287                                 }
9288                         }
9289
9290                         // copy view into the screen texture
9291                         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);
9292                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9293                 }
9294                 else if (!r_bloomstate.texture_bloom)
9295                 {
9296                         // we may still have to do view tint...
9297                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9298                         {
9299                                 // apply a color tint to the whole view
9300                                 R_ResetViewRendering2D();
9301                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9302                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9303                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9304                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9305                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9306                         }
9307                         break; // no screen processing, no bloom, skip it
9308                 }
9309
9310                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9311                 {
9312                         // render simple bloom effect
9313                         // copy the screen and shrink it and darken it for the bloom process
9314                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9315                         // make the bloom texture
9316                         R_Bloom_MakeTexture();
9317                 }
9318
9319 #if _MSC_VER >= 1400
9320 #define sscanf sscanf_s
9321 #endif
9322                 memset(uservecs, 0, sizeof(uservecs));
9323                 if (r_glsl_postprocess_uservec1_enable.integer)
9324                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9325                 if (r_glsl_postprocess_uservec2_enable.integer)
9326                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9327                 if (r_glsl_postprocess_uservec3_enable.integer)
9328                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9329                 if (r_glsl_postprocess_uservec4_enable.integer)
9330                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9331
9332                 R_ResetViewRendering2D();
9333                 GL_Color(1, 1, 1, 1);
9334                 GL_BlendFunc(GL_ONE, GL_ZERO);
9335
9336                 switch(vid.renderpath)
9337                 {
9338                 case RENDERPATH_GL20:
9339                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9340                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9341                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9342                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9343                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9344                         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]);
9345                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9346                         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]);
9347                         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]);
9348                         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]);
9349                         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]);
9350                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9351                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9352                         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);
9353                         break;
9354                 case RENDERPATH_CGGL:
9355 #ifdef SUPPORTCG
9356                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9357                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9358                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9359                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9360                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9361                         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
9362                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9363                         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
9364                         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
9365                         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
9366                         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
9367                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9368                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9369                         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);
9370 #endif
9371                         break;
9372                 case RENDERPATH_D3D9:
9373 #ifdef SUPPORTD3D
9374                         // 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...
9375                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9376                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9377                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9378                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9379                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9380                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9381                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9382                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9383                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9384                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9385                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9386                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9387                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9388                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9389 #endif
9390                         break;
9391                 case RENDERPATH_D3D10:
9392                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9393                         break;
9394                 case RENDERPATH_D3D11:
9395                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9396                         break;
9397                 default:
9398                         break;
9399                 }
9400                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9401                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9402                 break;
9403         case RENDERPATH_GL13:
9404         case RENDERPATH_GL11:
9405                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9406                 {
9407                         // apply a color tint to the whole view
9408                         R_ResetViewRendering2D();
9409                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9410                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9411                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9412                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9413                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9414                 }
9415                 break;
9416         }
9417 }
9418
9419 matrix4x4_t r_waterscrollmatrix;
9420
9421 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9422 {
9423         if (r_refdef.fog_density)
9424         {
9425                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9426                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9427                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9428
9429                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9430                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9431                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9432                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9433
9434                 {
9435                         vec3_t fogvec;
9436                         VectorCopy(r_refdef.fogcolor, fogvec);
9437                         //   color.rgb *= ContrastBoost * SceneBrightness;
9438                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9439                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9440                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9441                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9442                 }
9443         }
9444 }
9445
9446 void R_UpdateVariables(void)
9447 {
9448         R_Textures_Frame();
9449
9450         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9451
9452         r_refdef.farclip = r_farclip_base.value;
9453         if (r_refdef.scene.worldmodel)
9454                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9455         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9456
9457         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9458                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9459         r_refdef.polygonfactor = 0;
9460         r_refdef.polygonoffset = 0;
9461         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9462         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9463
9464         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9465         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9466         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9467         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9468         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9469         if (FAKELIGHT_ENABLED)
9470         {
9471                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9472         }
9473         if (r_showsurfaces.integer)
9474         {
9475                 r_refdef.scene.rtworld = false;
9476                 r_refdef.scene.rtworldshadows = false;
9477                 r_refdef.scene.rtdlight = false;
9478                 r_refdef.scene.rtdlightshadows = false;
9479                 r_refdef.lightmapintensity = 0;
9480         }
9481
9482         if (gamemode == GAME_NEHAHRA)
9483         {
9484                 if (gl_fogenable.integer)
9485                 {
9486                         r_refdef.oldgl_fogenable = true;
9487                         r_refdef.fog_density = gl_fogdensity.value;
9488                         r_refdef.fog_red = gl_fogred.value;
9489                         r_refdef.fog_green = gl_foggreen.value;
9490                         r_refdef.fog_blue = gl_fogblue.value;
9491                         r_refdef.fog_alpha = 1;
9492                         r_refdef.fog_start = 0;
9493                         r_refdef.fog_end = gl_skyclip.value;
9494                         r_refdef.fog_height = 1<<30;
9495                         r_refdef.fog_fadedepth = 128;
9496                 }
9497                 else if (r_refdef.oldgl_fogenable)
9498                 {
9499                         r_refdef.oldgl_fogenable = false;
9500                         r_refdef.fog_density = 0;
9501                         r_refdef.fog_red = 0;
9502                         r_refdef.fog_green = 0;
9503                         r_refdef.fog_blue = 0;
9504                         r_refdef.fog_alpha = 0;
9505                         r_refdef.fog_start = 0;
9506                         r_refdef.fog_end = 0;
9507                         r_refdef.fog_height = 1<<30;
9508                         r_refdef.fog_fadedepth = 128;
9509                 }
9510         }
9511
9512         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9513         r_refdef.fog_start = max(0, r_refdef.fog_start);
9514         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9515
9516         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9517
9518         if (r_refdef.fog_density && r_drawfog.integer)
9519         {
9520                 r_refdef.fogenabled = true;
9521                 // this is the point where the fog reaches 0.9986 alpha, which we
9522                 // consider a good enough cutoff point for the texture
9523                 // (0.9986 * 256 == 255.6)
9524                 if (r_fog_exp2.integer)
9525                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9526                 else
9527                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9528                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9529                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9530                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9531                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9532                         R_BuildFogHeightTexture();
9533                 // fog color was already set
9534                 // update the fog texture
9535                 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)
9536                         R_BuildFogTexture();
9537                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9538                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9539         }
9540         else
9541                 r_refdef.fogenabled = false;
9542
9543         switch(vid.renderpath)
9544         {
9545         case RENDERPATH_GL20:
9546         case RENDERPATH_CGGL:
9547         case RENDERPATH_D3D9:
9548         case RENDERPATH_D3D10:
9549         case RENDERPATH_D3D11:
9550                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9551                 {
9552                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9553                         {
9554                                 // build GLSL gamma texture
9555 #define RAMPWIDTH 256
9556                                 unsigned short ramp[RAMPWIDTH * 3];
9557                                 unsigned char rampbgr[RAMPWIDTH][4];
9558                                 int i;
9559
9560                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9561
9562                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9563                                 for(i = 0; i < RAMPWIDTH; ++i)
9564                                 {
9565                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9566                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9567                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9568                                         rampbgr[i][3] = 0;
9569                                 }
9570                                 if (r_texture_gammaramps)
9571                                 {
9572                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9573                                 }
9574                                 else
9575                                 {
9576                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9577                                 }
9578                         }
9579                 }
9580                 else
9581                 {
9582                         // remove GLSL gamma texture
9583                 }
9584                 break;
9585         case RENDERPATH_GL13:
9586         case RENDERPATH_GL11:
9587                 break;
9588         }
9589 }
9590
9591 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9592 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9593 /*
9594 ================
9595 R_SelectScene
9596 ================
9597 */
9598 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9599         if( scenetype != r_currentscenetype ) {
9600                 // store the old scenetype
9601                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9602                 r_currentscenetype = scenetype;
9603                 // move in the new scene
9604                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9605         }
9606 }
9607
9608 /*
9609 ================
9610 R_GetScenePointer
9611 ================
9612 */
9613 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9614 {
9615         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9616         if( scenetype == r_currentscenetype ) {
9617                 return &r_refdef.scene;
9618         } else {
9619                 return &r_scenes_store[ scenetype ];
9620         }
9621 }
9622
9623 /*
9624 ================
9625 R_RenderView
9626 ================
9627 */
9628 void R_RenderView(void)
9629 {
9630         if (r_timereport_active)
9631                 R_TimeReport("start");
9632         r_textureframe++; // used only by R_GetCurrentTexture
9633         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9634
9635         if(R_CompileShader_CheckStaticParms())
9636                 R_GLSL_Restart_f();
9637
9638         if (!r_drawentities.integer)
9639                 r_refdef.scene.numentities = 0;
9640
9641         R_AnimCache_ClearCache();
9642         R_FrameData_NewFrame();
9643
9644         if (r_refdef.view.isoverlay)
9645         {
9646                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9647                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9648                 R_TimeReport("depthclear");
9649
9650                 r_refdef.view.showdebug = false;
9651
9652                 r_waterstate.enabled = false;
9653                 r_waterstate.numwaterplanes = 0;
9654
9655                 R_RenderScene();
9656
9657                 CHECKGLERROR
9658                 return;
9659         }
9660
9661         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9662                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9663
9664         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9665
9666         R_RenderView_UpdateViewVectors();
9667
9668         R_Shadow_UpdateWorldLightSelection();
9669
9670         R_Bloom_StartFrame();
9671         R_Water_StartFrame();
9672
9673         CHECKGLERROR
9674         if (r_timereport_active)
9675                 R_TimeReport("viewsetup");
9676
9677         R_ResetViewRendering3D();
9678
9679         if (r_refdef.view.clear || r_refdef.fogenabled)
9680         {
9681                 R_ClearScreen(r_refdef.fogenabled);
9682                 if (r_timereport_active)
9683                         R_TimeReport("viewclear");
9684         }
9685         r_refdef.view.clear = true;
9686
9687         // this produces a bloom texture to be used in R_BlendView() later
9688         if (r_hdr.integer && r_bloomstate.bloomwidth)
9689         {
9690                 R_HDR_RenderBloomTexture();
9691                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9692                 r_textureframe++; // used only by R_GetCurrentTexture
9693         }
9694
9695         r_refdef.view.showdebug = true;
9696
9697         R_View_Update();
9698         if (r_timereport_active)
9699                 R_TimeReport("visibility");
9700
9701         r_waterstate.numwaterplanes = 0;
9702         if (r_waterstate.enabled)
9703                 R_RenderWaterPlanes();
9704
9705         R_RenderScene();
9706         r_waterstate.numwaterplanes = 0;
9707
9708         R_BlendView();
9709         if (r_timereport_active)
9710                 R_TimeReport("blendview");
9711
9712         GL_Scissor(0, 0, vid.width, vid.height);
9713         GL_ScissorTest(false);
9714
9715         CHECKGLERROR
9716 }
9717
9718 void R_RenderWaterPlanes(void)
9719 {
9720         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9721         {
9722                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9723                 if (r_timereport_active)
9724                         R_TimeReport("waterworld");
9725         }
9726
9727         // don't let sound skip if going slow
9728         if (r_refdef.scene.extraupdate)
9729                 S_ExtraUpdate ();
9730
9731         R_DrawModelsAddWaterPlanes();
9732         if (r_timereport_active)
9733                 R_TimeReport("watermodels");
9734
9735         if (r_waterstate.numwaterplanes)
9736         {
9737                 R_Water_ProcessPlanes();
9738                 if (r_timereport_active)
9739                         R_TimeReport("waterscenes");
9740         }
9741 }
9742
9743 extern void R_DrawLightningBeams (void);
9744 extern void VM_CL_AddPolygonsToMeshQueue (void);
9745 extern void R_DrawPortals (void);
9746 extern cvar_t cl_locs_show;
9747 static void R_DrawLocs(void);
9748 static void R_DrawEntityBBoxes(void);
9749 static void R_DrawModelDecals(void);
9750 extern void R_DrawModelShadows(void);
9751 extern void R_DrawModelShadowMaps(void);
9752 extern cvar_t cl_decals_newsystem;
9753 extern qboolean r_shadow_usingdeferredprepass;
9754 void R_RenderScene(void)
9755 {
9756         qboolean shadowmapping = false;
9757
9758         if (r_timereport_active)
9759                 R_TimeReport("beginscene");
9760
9761         r_refdef.stats.renders++;
9762
9763         R_UpdateFogColor();
9764
9765         // don't let sound skip if going slow
9766         if (r_refdef.scene.extraupdate)
9767                 S_ExtraUpdate ();
9768
9769         R_MeshQueue_BeginScene();
9770
9771         R_SkyStartFrame();
9772
9773         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);
9774
9775         if (r_timereport_active)
9776                 R_TimeReport("skystartframe");
9777
9778         if (cl.csqc_vidvars.drawworld)
9779         {
9780                 // don't let sound skip if going slow
9781                 if (r_refdef.scene.extraupdate)
9782                         S_ExtraUpdate ();
9783
9784                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9785                 {
9786                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9787                         if (r_timereport_active)
9788                                 R_TimeReport("worldsky");
9789                 }
9790
9791                 if (R_DrawBrushModelsSky() && r_timereport_active)
9792                         R_TimeReport("bmodelsky");
9793
9794                 if (skyrendermasked && skyrenderlater)
9795                 {
9796                         // we have to force off the water clipping plane while rendering sky
9797                         R_SetupView(false);
9798                         R_Sky();
9799                         R_SetupView(true);
9800                         if (r_timereport_active)
9801                                 R_TimeReport("sky");
9802                 }
9803         }
9804
9805         R_AnimCache_CacheVisibleEntities();
9806         if (r_timereport_active)
9807                 R_TimeReport("animation");
9808
9809         R_Shadow_PrepareLights();
9810         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9811                 R_Shadow_PrepareModelShadows();
9812         if (r_timereport_active)
9813                 R_TimeReport("preparelights");
9814
9815         if (R_Shadow_ShadowMappingEnabled())
9816                 shadowmapping = true;
9817
9818         if (r_shadow_usingdeferredprepass)
9819                 R_Shadow_DrawPrepass();
9820
9821         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9822         {
9823                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9824                 if (r_timereport_active)
9825                         R_TimeReport("worlddepth");
9826         }
9827         if (r_depthfirst.integer >= 2)
9828         {
9829                 R_DrawModelsDepth();
9830                 if (r_timereport_active)
9831                         R_TimeReport("modeldepth");
9832         }
9833
9834         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9835         {
9836                 R_DrawModelShadowMaps();
9837                 R_ResetViewRendering3D();
9838                 // don't let sound skip if going slow
9839                 if (r_refdef.scene.extraupdate)
9840                         S_ExtraUpdate ();
9841         }
9842
9843         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9844         {
9845                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9846                 if (r_timereport_active)
9847                         R_TimeReport("world");
9848         }
9849
9850         // don't let sound skip if going slow
9851         if (r_refdef.scene.extraupdate)
9852                 S_ExtraUpdate ();
9853
9854         R_DrawModels();
9855         if (r_timereport_active)
9856                 R_TimeReport("models");
9857
9858         // don't let sound skip if going slow
9859         if (r_refdef.scene.extraupdate)
9860                 S_ExtraUpdate ();
9861
9862         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9863         {
9864                 R_DrawModelShadows();
9865                 R_ResetViewRendering3D();
9866                 // don't let sound skip if going slow
9867                 if (r_refdef.scene.extraupdate)
9868                         S_ExtraUpdate ();
9869         }
9870
9871         if (!r_shadow_usingdeferredprepass)
9872         {
9873                 R_Shadow_DrawLights();
9874                 if (r_timereport_active)
9875                         R_TimeReport("rtlights");
9876         }
9877
9878         // don't let sound skip if going slow
9879         if (r_refdef.scene.extraupdate)
9880                 S_ExtraUpdate ();
9881
9882         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9883         {
9884                 R_DrawModelShadows();
9885                 R_ResetViewRendering3D();
9886                 // don't let sound skip if going slow
9887                 if (r_refdef.scene.extraupdate)
9888                         S_ExtraUpdate ();
9889         }
9890
9891         if (cl.csqc_vidvars.drawworld)
9892         {
9893                 if (cl_decals_newsystem.integer)
9894                 {
9895                         R_DrawModelDecals();
9896                         if (r_timereport_active)
9897                                 R_TimeReport("modeldecals");
9898                 }
9899                 else
9900                 {
9901                         R_DrawDecals();
9902                         if (r_timereport_active)
9903                                 R_TimeReport("decals");
9904                 }
9905
9906                 R_DrawParticles();
9907                 if (r_timereport_active)
9908                         R_TimeReport("particles");
9909
9910                 R_DrawExplosions();
9911                 if (r_timereport_active)
9912                         R_TimeReport("explosions");
9913
9914                 R_DrawLightningBeams();
9915                 if (r_timereport_active)
9916                         R_TimeReport("lightning");
9917         }
9918
9919         VM_CL_AddPolygonsToMeshQueue();
9920
9921         if (r_refdef.view.showdebug)
9922         {
9923                 if (cl_locs_show.integer)
9924                 {
9925                         R_DrawLocs();
9926                         if (r_timereport_active)
9927                                 R_TimeReport("showlocs");
9928                 }
9929
9930                 if (r_drawportals.integer)
9931                 {
9932                         R_DrawPortals();
9933                         if (r_timereport_active)
9934                                 R_TimeReport("portals");
9935                 }
9936
9937                 if (r_showbboxes.value > 0)
9938                 {
9939                         R_DrawEntityBBoxes();
9940                         if (r_timereport_active)
9941                                 R_TimeReport("bboxes");
9942                 }
9943         }
9944
9945         R_MeshQueue_RenderTransparent();
9946         if (r_timereport_active)
9947                 R_TimeReport("drawtrans");
9948
9949         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))
9950         {
9951                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9952                 if (r_timereport_active)
9953                         R_TimeReport("worlddebug");
9954                 R_DrawModelsDebug();
9955                 if (r_timereport_active)
9956                         R_TimeReport("modeldebug");
9957         }
9958
9959         if (cl.csqc_vidvars.drawworld)
9960         {
9961                 R_Shadow_DrawCoronas();
9962                 if (r_timereport_active)
9963                         R_TimeReport("coronas");
9964         }
9965
9966 #if 0
9967         {
9968                 GL_DepthTest(false);
9969                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9970                 GL_Color(1, 1, 1, 1);
9971                 qglBegin(GL_POLYGON);
9972                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9973                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9974                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9975                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9976                 qglEnd();
9977                 qglBegin(GL_POLYGON);
9978                 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]);
9979                 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]);
9980                 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]);
9981                 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]);
9982                 qglEnd();
9983                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9984         }
9985 #endif
9986
9987         // don't let sound skip if going slow
9988         if (r_refdef.scene.extraupdate)
9989                 S_ExtraUpdate ();
9990
9991         R_ResetViewRendering2D();
9992 }
9993
9994 static const unsigned short bboxelements[36] =
9995 {
9996         5, 1, 3, 5, 3, 7,
9997         6, 2, 0, 6, 0, 4,
9998         7, 3, 2, 7, 2, 6,
9999         4, 0, 1, 4, 1, 5,
10000         4, 5, 7, 4, 7, 6,
10001         1, 0, 2, 1, 2, 3,
10002 };
10003
10004 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
10005 {
10006         int i;
10007         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
10008
10009         RSurf_ActiveWorldEntity();
10010
10011         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10012         GL_DepthMask(false);
10013         GL_DepthRange(0, 1);
10014         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10015 //      R_Mesh_ResetTextureState();
10016
10017         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
10018         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
10019         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
10020         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
10021         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
10022         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
10023         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
10024         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
10025         R_FillColors(color4f, 8, cr, cg, cb, ca);
10026         if (r_refdef.fogenabled)
10027         {
10028                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
10029                 {
10030                         f1 = RSurf_FogVertex(v);
10031                         f2 = 1 - f1;
10032                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
10033                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
10034                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
10035                 }
10036         }
10037         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
10038         R_Mesh_ResetTextureState();
10039         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10040         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
10041 }
10042
10043 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10044 {
10045         int i;
10046         float color[4];
10047         prvm_edict_t *edict;
10048         prvm_prog_t *prog_save = prog;
10049
10050         // this function draws bounding boxes of server entities
10051         if (!sv.active)
10052                 return;
10053
10054         GL_CullFace(GL_NONE);
10055         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10056
10057         prog = 0;
10058         SV_VM_Begin();
10059         for (i = 0;i < numsurfaces;i++)
10060         {
10061                 edict = PRVM_EDICT_NUM(surfacelist[i]);
10062                 switch ((int)edict->fields.server->solid)
10063                 {
10064                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
10065                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
10066                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
10067                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
10068                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
10069                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
10070                 }
10071                 color[3] *= r_showbboxes.value;
10072                 color[3] = bound(0, color[3], 1);
10073                 GL_DepthTest(!r_showdisabledepthtest.integer);
10074                 GL_CullFace(r_refdef.view.cullface_front);
10075                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10076         }
10077         SV_VM_End();
10078         prog = prog_save;
10079 }
10080
10081 static void R_DrawEntityBBoxes(void)
10082 {
10083         int i;
10084         prvm_edict_t *edict;
10085         vec3_t center;
10086         prvm_prog_t *prog_save = prog;
10087
10088         // this function draws bounding boxes of server entities
10089         if (!sv.active)
10090                 return;
10091
10092         prog = 0;
10093         SV_VM_Begin();
10094         for (i = 0;i < prog->num_edicts;i++)
10095         {
10096                 edict = PRVM_EDICT_NUM(i);
10097                 if (edict->priv.server->free)
10098                         continue;
10099                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10100                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10101                         continue;
10102                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10103                         continue;
10104                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10105                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10106         }
10107         SV_VM_End();
10108         prog = prog_save;
10109 }
10110
10111 static const int nomodelelement3i[24] =
10112 {
10113         5, 2, 0,
10114         5, 1, 2,
10115         5, 0, 3,
10116         5, 3, 1,
10117         0, 2, 4,
10118         2, 1, 4,
10119         3, 0, 4,
10120         1, 3, 4
10121 };
10122
10123 static const unsigned short nomodelelement3s[24] =
10124 {
10125         5, 2, 0,
10126         5, 1, 2,
10127         5, 0, 3,
10128         5, 3, 1,
10129         0, 2, 4,
10130         2, 1, 4,
10131         3, 0, 4,
10132         1, 3, 4
10133 };
10134
10135 static const float nomodelvertex3f[6*3] =
10136 {
10137         -16,   0,   0,
10138          16,   0,   0,
10139           0, -16,   0,
10140           0,  16,   0,
10141           0,   0, -16,
10142           0,   0,  16
10143 };
10144
10145 static const float nomodelcolor4f[6*4] =
10146 {
10147         0.0f, 0.0f, 0.5f, 1.0f,
10148         0.0f, 0.0f, 0.5f, 1.0f,
10149         0.0f, 0.5f, 0.0f, 1.0f,
10150         0.0f, 0.5f, 0.0f, 1.0f,
10151         0.5f, 0.0f, 0.0f, 1.0f,
10152         0.5f, 0.0f, 0.0f, 1.0f
10153 };
10154
10155 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10156 {
10157         int i;
10158         float f1, f2, *c;
10159         float color4f[6*4];
10160
10161         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);
10162
10163         // this is only called once per entity so numsurfaces is always 1, and
10164         // surfacelist is always {0}, so this code does not handle batches
10165
10166         if (rsurface.ent_flags & RENDER_ADDITIVE)
10167         {
10168                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10169                 GL_DepthMask(false);
10170         }
10171         else if (rsurface.colormod[3] < 1)
10172         {
10173                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10174                 GL_DepthMask(false);
10175         }
10176         else
10177         {
10178                 GL_BlendFunc(GL_ONE, GL_ZERO);
10179                 GL_DepthMask(true);
10180         }
10181         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10182         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10183         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10184         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10185         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10186         for (i = 0, c = color4f;i < 6;i++, c += 4)
10187         {
10188                 c[0] *= rsurface.colormod[0];
10189                 c[1] *= rsurface.colormod[1];
10190                 c[2] *= rsurface.colormod[2];
10191                 c[3] *= rsurface.colormod[3];
10192         }
10193         if (r_refdef.fogenabled)
10194         {
10195                 for (i = 0, c = color4f;i < 6;i++, c += 4)
10196                 {
10197                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10198                         f2 = 1 - f1;
10199                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10200                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10201                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10202                 }
10203         }
10204 //      R_Mesh_ResetTextureState();
10205         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10206         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10207         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10208 }
10209
10210 void R_DrawNoModel(entity_render_t *ent)
10211 {
10212         vec3_t org;
10213         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10214         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10215                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10216         else
10217                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10218 }
10219
10220 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10221 {
10222         vec3_t right1, right2, diff, normal;
10223
10224         VectorSubtract (org2, org1, normal);
10225
10226         // calculate 'right' vector for start
10227         VectorSubtract (r_refdef.view.origin, org1, diff);
10228         CrossProduct (normal, diff, right1);
10229         VectorNormalize (right1);
10230
10231         // calculate 'right' vector for end
10232         VectorSubtract (r_refdef.view.origin, org2, diff);
10233         CrossProduct (normal, diff, right2);
10234         VectorNormalize (right2);
10235
10236         vert[ 0] = org1[0] + width * right1[0];
10237         vert[ 1] = org1[1] + width * right1[1];
10238         vert[ 2] = org1[2] + width * right1[2];
10239         vert[ 3] = org1[0] - width * right1[0];
10240         vert[ 4] = org1[1] - width * right1[1];
10241         vert[ 5] = org1[2] - width * right1[2];
10242         vert[ 6] = org2[0] - width * right2[0];
10243         vert[ 7] = org2[1] - width * right2[1];
10244         vert[ 8] = org2[2] - width * right2[2];
10245         vert[ 9] = org2[0] + width * right2[0];
10246         vert[10] = org2[1] + width * right2[1];
10247         vert[11] = org2[2] + width * right2[2];
10248 }
10249
10250 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)
10251 {
10252         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10253         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10254         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10255         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10256         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10257         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10258         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10259         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10260         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10261         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10262         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10263         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10264 }
10265
10266 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10267 {
10268         int i;
10269         float *vertex3f;
10270         float v[3];
10271         VectorSet(v, x, y, z);
10272         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10273                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10274                         break;
10275         if (i == mesh->numvertices)
10276         {
10277                 if (mesh->numvertices < mesh->maxvertices)
10278                 {
10279                         VectorCopy(v, vertex3f);
10280                         mesh->numvertices++;
10281                 }
10282                 return mesh->numvertices;
10283         }
10284         else
10285                 return i;
10286 }
10287
10288 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10289 {
10290         int i;
10291         int *e, element[3];
10292         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10293         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10294         e = mesh->element3i + mesh->numtriangles * 3;
10295         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10296         {
10297                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10298                 if (mesh->numtriangles < mesh->maxtriangles)
10299                 {
10300                         *e++ = element[0];
10301                         *e++ = element[1];
10302                         *e++ = element[2];
10303                         mesh->numtriangles++;
10304                 }
10305                 element[1] = element[2];
10306         }
10307 }
10308
10309 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10310 {
10311         int i;
10312         int *e, element[3];
10313         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10314         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10315         e = mesh->element3i + mesh->numtriangles * 3;
10316         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10317         {
10318                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10319                 if (mesh->numtriangles < mesh->maxtriangles)
10320                 {
10321                         *e++ = element[0];
10322                         *e++ = element[1];
10323                         *e++ = element[2];
10324                         mesh->numtriangles++;
10325                 }
10326                 element[1] = element[2];
10327         }
10328 }
10329
10330 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10331 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10332 {
10333         int planenum, planenum2;
10334         int w;
10335         int tempnumpoints;
10336         mplane_t *plane, *plane2;
10337         double maxdist;
10338         double temppoints[2][256*3];
10339         // figure out how large a bounding box we need to properly compute this brush
10340         maxdist = 0;
10341         for (w = 0;w < numplanes;w++)
10342                 maxdist = max(maxdist, fabs(planes[w].dist));
10343         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10344         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10345         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10346         {
10347                 w = 0;
10348                 tempnumpoints = 4;
10349                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10350                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10351                 {
10352                         if (planenum2 == planenum)
10353                                 continue;
10354                         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);
10355                         w = !w;
10356                 }
10357                 if (tempnumpoints < 3)
10358                         continue;
10359                 // generate elements forming a triangle fan for this polygon
10360                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10361         }
10362 }
10363
10364 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)
10365 {
10366         texturelayer_t *layer;
10367         layer = t->currentlayers + t->currentnumlayers++;
10368         layer->type = type;
10369         layer->depthmask = depthmask;
10370         layer->blendfunc1 = blendfunc1;
10371         layer->blendfunc2 = blendfunc2;
10372         layer->texture = texture;
10373         layer->texmatrix = *matrix;
10374         layer->color[0] = r;
10375         layer->color[1] = g;
10376         layer->color[2] = b;
10377         layer->color[3] = a;
10378 }
10379
10380 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10381 {
10382         if(parms[0] == 0 && parms[1] == 0)
10383                 return false;
10384         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10385                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10386                         return false;
10387         return true;
10388 }
10389
10390 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10391 {
10392         double index, f;
10393         index = parms[2] + r_refdef.scene.time * parms[3];
10394         index -= floor(index);
10395         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10396         {
10397         default:
10398         case Q3WAVEFUNC_NONE:
10399         case Q3WAVEFUNC_NOISE:
10400         case Q3WAVEFUNC_COUNT:
10401                 f = 0;
10402                 break;
10403         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10404         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10405         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10406         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10407         case Q3WAVEFUNC_TRIANGLE:
10408                 index *= 4;
10409                 f = index - floor(index);
10410                 if (index < 1)
10411                         f = f;
10412                 else if (index < 2)
10413                         f = 1 - f;
10414                 else if (index < 3)
10415                         f = -f;
10416                 else
10417                         f = -(1 - f);
10418                 break;
10419         }
10420         f = parms[0] + parms[1] * f;
10421         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10422                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10423         return (float) f;
10424 }
10425
10426 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10427 {
10428         int w, h, idx;
10429         float f;
10430         float tcmat[12];
10431         matrix4x4_t matrix, temp;
10432         switch(tcmod->tcmod)
10433         {
10434                 case Q3TCMOD_COUNT:
10435                 case Q3TCMOD_NONE:
10436                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10437                                 matrix = r_waterscrollmatrix;
10438                         else
10439                                 matrix = identitymatrix;
10440                         break;
10441                 case Q3TCMOD_ENTITYTRANSLATE:
10442                         // this is used in Q3 to allow the gamecode to control texcoord
10443                         // scrolling on the entity, which is not supported in darkplaces yet.
10444                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10445                         break;
10446                 case Q3TCMOD_ROTATE:
10447                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10448                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10449                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10450                         break;
10451                 case Q3TCMOD_SCALE:
10452                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10453                         break;
10454                 case Q3TCMOD_SCROLL:
10455                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10456                         break;
10457                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10458                         w = (int) tcmod->parms[0];
10459                         h = (int) tcmod->parms[1];
10460                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10461                         f = f - floor(f);
10462                         idx = (int) floor(f * w * h);
10463                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10464                         break;
10465                 case Q3TCMOD_STRETCH:
10466                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10467                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10468                         break;
10469                 case Q3TCMOD_TRANSFORM:
10470                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10471                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10472                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10473                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10474                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10475                         break;
10476                 case Q3TCMOD_TURBULENT:
10477                         // this is handled in the RSurf_PrepareVertices function
10478                         matrix = identitymatrix;
10479                         break;
10480         }
10481         temp = *texmatrix;
10482         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10483 }
10484
10485 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10486 {
10487         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10488         char name[MAX_QPATH];
10489         skinframe_t *skinframe;
10490         unsigned char pixels[296*194];
10491         strlcpy(cache->name, skinname, sizeof(cache->name));
10492         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10493         if (developer_loading.integer)
10494                 Con_Printf("loading %s\n", name);
10495         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10496         if (!skinframe || !skinframe->base)
10497         {
10498                 unsigned char *f;
10499                 fs_offset_t filesize;
10500                 skinframe = NULL;
10501                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10502                 if (f)
10503                 {
10504                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10505                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10506                         Mem_Free(f);
10507                 }
10508         }
10509         cache->skinframe = skinframe;
10510 }
10511
10512 texture_t *R_GetCurrentTexture(texture_t *t)
10513 {
10514         int i;
10515         const entity_render_t *ent = rsurface.entity;
10516         dp_model_t *model = ent->model;
10517         q3shaderinfo_layer_tcmod_t *tcmod;
10518
10519         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10520                 return t->currentframe;
10521         t->update_lastrenderframe = r_textureframe;
10522         t->update_lastrenderentity = (void *)ent;
10523
10524         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10525                 t->camera_entity = ent->entitynumber;
10526         else
10527                 t->camera_entity = 0;
10528
10529         // switch to an alternate material if this is a q1bsp animated material
10530         {
10531                 texture_t *texture = t;
10532                 int s = rsurface.ent_skinnum;
10533                 if ((unsigned int)s >= (unsigned int)model->numskins)
10534                         s = 0;
10535                 if (model->skinscenes)
10536                 {
10537                         if (model->skinscenes[s].framecount > 1)
10538                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10539                         else
10540                                 s = model->skinscenes[s].firstframe;
10541                 }
10542                 if (s > 0)
10543                         t = t + s * model->num_surfaces;
10544                 if (t->animated)
10545                 {
10546                         // use an alternate animation if the entity's frame is not 0,
10547                         // and only if the texture has an alternate animation
10548                         if (rsurface.ent_alttextures && t->anim_total[1])
10549                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10550                         else
10551                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10552                 }
10553                 texture->currentframe = t;
10554         }
10555
10556         // update currentskinframe to be a qw skin or animation frame
10557         if (rsurface.ent_qwskin >= 0)
10558         {
10559                 i = rsurface.ent_qwskin;
10560                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10561                 {
10562                         r_qwskincache_size = cl.maxclients;
10563                         if (r_qwskincache)
10564                                 Mem_Free(r_qwskincache);
10565                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10566                 }
10567                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10568                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10569                 t->currentskinframe = r_qwskincache[i].skinframe;
10570                 if (t->currentskinframe == NULL)
10571                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10572         }
10573         else if (t->numskinframes >= 2)
10574                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10575         if (t->backgroundnumskinframes >= 2)
10576                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10577
10578         t->currentmaterialflags = t->basematerialflags;
10579         t->currentalpha = rsurface.colormod[3];
10580         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10581                 t->currentalpha *= r_wateralpha.value;
10582         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10583                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10584         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10585                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10586         if (!(rsurface.ent_flags & RENDER_LIGHT))
10587                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10588         else if (FAKELIGHT_ENABLED)
10589         {
10590                         // no modellight if using fakelight for the map
10591         }
10592         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10593         {
10594                 // pick a model lighting mode
10595                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10596                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10597                 else
10598                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10599         }
10600         if (rsurface.ent_flags & RENDER_ADDITIVE)
10601                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10602         else if (t->currentalpha < 1)
10603                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10604         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10605                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10606         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10607                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10608         if (t->backgroundnumskinframes)
10609                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10610         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10611         {
10612                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10613                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10614         }
10615         else
10616                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10617         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10618                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10619
10620         // there is no tcmod
10621         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10622         {
10623                 t->currenttexmatrix = r_waterscrollmatrix;
10624                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10625         }
10626         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10627         {
10628                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10629                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10630         }
10631
10632         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10633                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10634         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10635                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10636
10637         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10638         if (t->currentskinframe->qpixels)
10639                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10640         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10641         if (!t->basetexture)
10642                 t->basetexture = r_texture_notexture;
10643         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10644         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10645         t->nmaptexture = t->currentskinframe->nmap;
10646         if (!t->nmaptexture)
10647                 t->nmaptexture = r_texture_blanknormalmap;
10648         t->glosstexture = r_texture_black;
10649         t->glowtexture = t->currentskinframe->glow;
10650         t->fogtexture = t->currentskinframe->fog;
10651         t->reflectmasktexture = t->currentskinframe->reflect;
10652         if (t->backgroundnumskinframes)
10653         {
10654                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10655                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10656                 t->backgroundglosstexture = r_texture_black;
10657                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10658                 if (!t->backgroundnmaptexture)
10659                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10660         }
10661         else
10662         {
10663                 t->backgroundbasetexture = r_texture_white;
10664                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10665                 t->backgroundglosstexture = r_texture_black;
10666                 t->backgroundglowtexture = NULL;
10667         }
10668         t->specularpower = r_shadow_glossexponent.value;
10669         // TODO: store reference values for these in the texture?
10670         t->specularscale = 0;
10671         if (r_shadow_gloss.integer > 0)
10672         {
10673                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10674                 {
10675                         if (r_shadow_glossintensity.value > 0)
10676                         {
10677                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10678                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10679                                 t->specularscale = r_shadow_glossintensity.value;
10680                         }
10681                 }
10682                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10683                 {
10684                         t->glosstexture = r_texture_white;
10685                         t->backgroundglosstexture = r_texture_white;
10686                         t->specularscale = r_shadow_gloss2intensity.value;
10687                         t->specularpower = r_shadow_gloss2exponent.value;
10688                 }
10689         }
10690         t->specularscale *= t->specularscalemod;
10691         t->specularpower *= t->specularpowermod;
10692
10693         // lightmaps mode looks bad with dlights using actual texturing, so turn
10694         // off the colormap and glossmap, but leave the normalmap on as it still
10695         // accurately represents the shading involved
10696         if (gl_lightmaps.integer)
10697         {
10698                 t->basetexture = r_texture_grey128;
10699                 t->pantstexture = r_texture_black;
10700                 t->shirttexture = r_texture_black;
10701                 t->nmaptexture = r_texture_blanknormalmap;
10702                 t->glosstexture = r_texture_black;
10703                 t->glowtexture = NULL;
10704                 t->fogtexture = NULL;
10705                 t->reflectmasktexture = NULL;
10706                 t->backgroundbasetexture = NULL;
10707                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10708                 t->backgroundglosstexture = r_texture_black;
10709                 t->backgroundglowtexture = NULL;
10710                 t->specularscale = 0;
10711                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10712         }
10713
10714         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10715         VectorClear(t->dlightcolor);
10716         t->currentnumlayers = 0;
10717         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10718         {
10719                 int blendfunc1, blendfunc2;
10720                 qboolean depthmask;
10721                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10722                 {
10723                         blendfunc1 = GL_SRC_ALPHA;
10724                         blendfunc2 = GL_ONE;
10725                 }
10726                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10727                 {
10728                         blendfunc1 = GL_SRC_ALPHA;
10729                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10730                 }
10731                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10732                 {
10733                         blendfunc1 = t->customblendfunc[0];
10734                         blendfunc2 = t->customblendfunc[1];
10735                 }
10736                 else
10737                 {
10738                         blendfunc1 = GL_ONE;
10739                         blendfunc2 = GL_ZERO;
10740                 }
10741                 // don't colormod evilblend textures
10742                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10743                         VectorSet(t->lightmapcolor, 1, 1, 1);
10744                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10745                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10746                 {
10747                         // fullbright is not affected by r_refdef.lightmapintensity
10748                         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]);
10749                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10750                                 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]);
10751                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10752                                 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]);
10753                 }
10754                 else
10755                 {
10756                         vec3_t ambientcolor;
10757                         float colorscale;
10758                         // set the color tint used for lights affecting this surface
10759                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10760                         colorscale = 2;
10761                         // q3bsp has no lightmap updates, so the lightstylevalue that
10762                         // would normally be baked into the lightmap must be
10763                         // applied to the color
10764                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10765                         if (model->type == mod_brushq3)
10766                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10767                         colorscale *= r_refdef.lightmapintensity;
10768                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10769                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10770                         // basic lit geometry
10771                         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]);
10772                         // add pants/shirt if needed
10773                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10774                                 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]);
10775                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10776                                 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]);
10777                         // now add ambient passes if needed
10778                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10779                         {
10780                                 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]);
10781                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10782                                         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]);
10783                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10784                                         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]);
10785                         }
10786                 }
10787                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10788                         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]);
10789                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10790                 {
10791                         // if this is opaque use alpha blend which will darken the earlier
10792                         // passes cheaply.
10793                         //
10794                         // if this is an alpha blended material, all the earlier passes
10795                         // were darkened by fog already, so we only need to add the fog
10796                         // color ontop through the fog mask texture
10797                         //
10798                         // if this is an additive blended material, all the earlier passes
10799                         // were darkened by fog already, and we should not add fog color
10800                         // (because the background was not darkened, there is no fog color
10801                         // that was lost behind it).
10802                         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]);
10803                 }
10804         }
10805
10806         return t->currentframe;
10807 }
10808
10809 rsurfacestate_t rsurface;
10810
10811 void R_Mesh_ResizeArrays(int newvertices)
10812 {
10813         unsigned char *base;
10814         size_t size;
10815         if (rsurface.array_size >= newvertices)
10816                 return;
10817         if (rsurface.array_base)
10818                 Mem_Free(rsurface.array_base);
10819         rsurface.array_size = (newvertices + 1023) & ~1023;
10820         size = 0;
10821         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10822         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10823         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10824         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10825         size += rsurface.array_size * sizeof(float[3]);
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[4]);
10834         size += rsurface.array_size * sizeof(float[2]);
10835         size += rsurface.array_size * sizeof(float[2]);
10836         size += rsurface.array_size * sizeof(float[4]);
10837         size += rsurface.array_size * sizeof(int[3]);
10838         size += rsurface.array_size * sizeof(unsigned short[3]);
10839         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10840         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10841         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10842         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10843         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10844         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10845         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10846         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10847         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10848         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10849         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10850         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10851         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10852         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10853         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10854         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10855         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10856         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
10857         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10858 }
10859
10860 void RSurf_ActiveWorldEntity(void)
10861 {
10862         dp_model_t *model = r_refdef.scene.worldmodel;
10863         //if (rsurface.entity == r_refdef.scene.worldentity)
10864         //      return;
10865         rsurface.entity = r_refdef.scene.worldentity;
10866         rsurface.skeleton = NULL;
10867         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10868         rsurface.ent_skinnum = 0;
10869         rsurface.ent_qwskin = -1;
10870         rsurface.ent_shadertime = 0;
10871         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10872         R_Mesh_ResizeArrays(max(model->surfmesh.num_vertices, model->surfmesh.num_triangles));
10873         rsurface.matrix = identitymatrix;
10874         rsurface.inversematrix = identitymatrix;
10875         rsurface.matrixscale = 1;
10876         rsurface.inversematrixscale = 1;
10877         R_EntityMatrix(&identitymatrix);
10878         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10879         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10880         rsurface.fograngerecip = r_refdef.fograngerecip;
10881         rsurface.fogheightfade = r_refdef.fogheightfade;
10882         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10883         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10884         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10885         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10886         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10887         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10888         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10889         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10890         rsurface.colormod[3] = 1;
10891         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);
10892         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10893         rsurface.frameblend[0].lerp = 1;
10894         rsurface.ent_alttextures = false;
10895         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10896         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10897         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10898         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10899         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10900         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10901         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10902         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10903         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10904         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10905         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10906         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10907         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10908         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10909         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10910         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10911         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10912         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10913         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10914         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10915         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10916         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10917         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10918         rsurface.modelelement3i = model->surfmesh.data_element3i;
10919         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10920         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10921         rsurface.modelelement3s = model->surfmesh.data_element3s;
10922         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10923         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10924         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10925         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10926         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10927         rsurface.modelsurfaces = model->data_surfaces;
10928         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10929         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10930         rsurface.modelvertexposition = model->surfmesh.vertexposition;
10931         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10932         rsurface.modelgeneratedvertex = false;
10933         rsurface.batchgeneratedvertex = false;
10934         rsurface.batchfirstvertex = 0;
10935         rsurface.batchnumvertices = 0;
10936         rsurface.batchfirsttriangle = 0;
10937         rsurface.batchnumtriangles = 0;
10938         rsurface.batchvertex3f  = NULL;
10939         rsurface.batchvertex3f_vertexbuffer = NULL;
10940         rsurface.batchvertex3f_bufferoffset = 0;
10941         rsurface.batchsvector3f = NULL;
10942         rsurface.batchsvector3f_vertexbuffer = NULL;
10943         rsurface.batchsvector3f_bufferoffset = 0;
10944         rsurface.batchtvector3f = NULL;
10945         rsurface.batchtvector3f_vertexbuffer = NULL;
10946         rsurface.batchtvector3f_bufferoffset = 0;
10947         rsurface.batchnormal3f  = NULL;
10948         rsurface.batchnormal3f_vertexbuffer = NULL;
10949         rsurface.batchnormal3f_bufferoffset = 0;
10950         rsurface.batchlightmapcolor4f = NULL;
10951         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10952         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10953         rsurface.batchtexcoordtexture2f = NULL;
10954         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10955         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10956         rsurface.batchtexcoordlightmap2f = NULL;
10957         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10958         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10959         rsurface.batchvertexmesh = NULL;
10960         rsurface.batchvertexmeshbuffer = NULL;
10961         rsurface.batchvertexposition = NULL;
10962         rsurface.batchvertexpositionbuffer = NULL;
10963         rsurface.batchelement3i = NULL;
10964         rsurface.batchelement3i_indexbuffer = NULL;
10965         rsurface.batchelement3i_bufferoffset = 0;
10966         rsurface.batchelement3s = NULL;
10967         rsurface.batchelement3s_indexbuffer = NULL;
10968         rsurface.batchelement3s_bufferoffset = 0;
10969         rsurface.passcolor4f = NULL;
10970         rsurface.passcolor4f_vertexbuffer = NULL;
10971         rsurface.passcolor4f_bufferoffset = 0;
10972 }
10973
10974 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10975 {
10976         dp_model_t *model = ent->model;
10977         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10978         //      return;
10979         rsurface.entity = (entity_render_t *)ent;
10980         rsurface.skeleton = ent->skeleton;
10981         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10982         rsurface.ent_skinnum = ent->skinnum;
10983         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;
10984         rsurface.ent_shadertime = ent->shadertime;
10985         rsurface.ent_flags = ent->flags;
10986         R_Mesh_ResizeArrays(max(model->surfmesh.num_vertices, model->surfmesh.num_triangles));
10987         rsurface.matrix = ent->matrix;
10988         rsurface.inversematrix = ent->inversematrix;
10989         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10990         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10991         R_EntityMatrix(&rsurface.matrix);
10992         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10993         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10994         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10995         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10996         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10997         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10998         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10999         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
11000         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
11001         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
11002         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
11003         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
11004         rsurface.colormod[3] = ent->alpha;
11005         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
11006         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
11007         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
11008         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11009         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11010         if (ent->model->brush.submodel && !prepass)
11011         {
11012                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
11013                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
11014         }
11015         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
11016         {
11017                 if (ent->animcache_vertex3f && !r_framedata_failed)
11018                 {
11019                         rsurface.modelvertex3f = ent->animcache_vertex3f;
11020                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
11021                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
11022                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
11023                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
11024                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
11025                         rsurface.modelvertexposition = ent->animcache_vertexposition;
11026                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
11027                 }
11028                 else if (wanttangents)
11029                 {
11030                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11031                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11032                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11033                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11034                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
11035                         rsurface.modelvertexmesh = NULL;
11036                         rsurface.modelvertexmeshbuffer = NULL;
11037                         rsurface.modelvertexposition = NULL;
11038                         rsurface.modelvertexpositionbuffer = NULL;
11039                 }
11040                 else if (wantnormals)
11041                 {
11042                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11043                         rsurface.modelsvector3f = NULL;
11044                         rsurface.modeltvector3f = NULL;
11045                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11046                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
11047                         rsurface.modelvertexmesh = NULL;
11048                         rsurface.modelvertexmeshbuffer = NULL;
11049                         rsurface.modelvertexposition = NULL;
11050                         rsurface.modelvertexpositionbuffer = NULL;
11051                 }
11052                 else
11053                 {
11054                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
11055                         rsurface.modelsvector3f = NULL;
11056                         rsurface.modeltvector3f = NULL;
11057                         rsurface.modelnormal3f = NULL;
11058                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
11059                         rsurface.modelvertexmesh = NULL;
11060                         rsurface.modelvertexmeshbuffer = NULL;
11061                         rsurface.modelvertexposition = NULL;
11062                         rsurface.modelvertexpositionbuffer = NULL;
11063                 }
11064                 rsurface.modelvertex3f_vertexbuffer = 0;
11065                 rsurface.modelvertex3f_bufferoffset = 0;
11066                 rsurface.modelsvector3f_vertexbuffer = 0;
11067                 rsurface.modelsvector3f_bufferoffset = 0;
11068                 rsurface.modeltvector3f_vertexbuffer = 0;
11069                 rsurface.modeltvector3f_bufferoffset = 0;
11070                 rsurface.modelnormal3f_vertexbuffer = 0;
11071                 rsurface.modelnormal3f_bufferoffset = 0;
11072                 rsurface.modelgeneratedvertex = true;
11073         }
11074         else
11075         {
11076                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
11077                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11078                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11079                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11080                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11081                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11082                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11083                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11084                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11085                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
11086                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11087                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11088                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11089                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11090                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
11091                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
11092                 rsurface.modelgeneratedvertex = false;
11093         }
11094         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11095         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11096         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11097         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11098         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11099         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11100         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11101         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11102         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11103         rsurface.modelelement3i = model->surfmesh.data_element3i;
11104         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11105         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11106         rsurface.modelelement3s = model->surfmesh.data_element3s;
11107         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11108         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11109         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11110         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11111         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11112         rsurface.modelsurfaces = model->data_surfaces;
11113         rsurface.batchgeneratedvertex = false;
11114         rsurface.batchfirstvertex = 0;
11115         rsurface.batchnumvertices = 0;
11116         rsurface.batchfirsttriangle = 0;
11117         rsurface.batchnumtriangles = 0;
11118         rsurface.batchvertex3f  = NULL;
11119         rsurface.batchvertex3f_vertexbuffer = NULL;
11120         rsurface.batchvertex3f_bufferoffset = 0;
11121         rsurface.batchsvector3f = NULL;
11122         rsurface.batchsvector3f_vertexbuffer = NULL;
11123         rsurface.batchsvector3f_bufferoffset = 0;
11124         rsurface.batchtvector3f = NULL;
11125         rsurface.batchtvector3f_vertexbuffer = NULL;
11126         rsurface.batchtvector3f_bufferoffset = 0;
11127         rsurface.batchnormal3f  = NULL;
11128         rsurface.batchnormal3f_vertexbuffer = NULL;
11129         rsurface.batchnormal3f_bufferoffset = 0;
11130         rsurface.batchlightmapcolor4f = NULL;
11131         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11132         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11133         rsurface.batchtexcoordtexture2f = NULL;
11134         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11135         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11136         rsurface.batchtexcoordlightmap2f = NULL;
11137         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11138         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11139         rsurface.batchvertexmesh = NULL;
11140         rsurface.batchvertexmeshbuffer = NULL;
11141         rsurface.batchvertexposition = NULL;
11142         rsurface.batchvertexpositionbuffer = NULL;
11143         rsurface.batchelement3i = NULL;
11144         rsurface.batchelement3i_indexbuffer = NULL;
11145         rsurface.batchelement3i_bufferoffset = 0;
11146         rsurface.batchelement3s = NULL;
11147         rsurface.batchelement3s_indexbuffer = NULL;
11148         rsurface.batchelement3s_bufferoffset = 0;
11149         rsurface.passcolor4f = NULL;
11150         rsurface.passcolor4f_vertexbuffer = NULL;
11151         rsurface.passcolor4f_bufferoffset = 0;
11152 }
11153
11154 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)
11155 {
11156         int i;
11157
11158         rsurface.entity = r_refdef.scene.worldentity;
11159         rsurface.skeleton = NULL;
11160         rsurface.ent_skinnum = 0;
11161         rsurface.ent_qwskin = -1;
11162         rsurface.ent_shadertime = shadertime;
11163         rsurface.ent_flags = entflags;
11164         rsurface.modelnumvertices = numvertices;
11165         rsurface.modelnumtriangles = numtriangles;
11166         R_Mesh_ResizeArrays(max(rsurface.modelnumvertices, rsurface.modelnumtriangles));
11167         rsurface.matrix = *matrix;
11168         rsurface.inversematrix = *inversematrix;
11169         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11170         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11171         R_EntityMatrix(&rsurface.matrix);
11172         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11173         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11174         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11175         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11176         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11177         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11178         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11179         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11180         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11181         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11182         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11183         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11184         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);
11185         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11186         rsurface.frameblend[0].lerp = 1;
11187         rsurface.ent_alttextures = false;
11188         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11189         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11190         if (wanttangents)
11191         {
11192                 rsurface.modelvertex3f = vertex3f;
11193                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
11194                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
11195                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11196         }
11197         else if (wantnormals)
11198         {
11199                 rsurface.modelvertex3f = vertex3f;
11200                 rsurface.modelsvector3f = NULL;
11201                 rsurface.modeltvector3f = NULL;
11202                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11203         }
11204         else
11205         {
11206                 rsurface.modelvertex3f = vertex3f;
11207                 rsurface.modelsvector3f = NULL;
11208                 rsurface.modeltvector3f = NULL;
11209                 rsurface.modelnormal3f = NULL;
11210         }
11211         rsurface.modelvertexmesh = NULL;
11212         rsurface.modelvertexmeshbuffer = NULL;
11213         rsurface.modelvertexposition = NULL;
11214         rsurface.modelvertexpositionbuffer = NULL;
11215         rsurface.modelvertex3f_vertexbuffer = 0;
11216         rsurface.modelvertex3f_bufferoffset = 0;
11217         rsurface.modelsvector3f_vertexbuffer = 0;
11218         rsurface.modelsvector3f_bufferoffset = 0;
11219         rsurface.modeltvector3f_vertexbuffer = 0;
11220         rsurface.modeltvector3f_bufferoffset = 0;
11221         rsurface.modelnormal3f_vertexbuffer = 0;
11222         rsurface.modelnormal3f_bufferoffset = 0;
11223         rsurface.modelgeneratedvertex = true;
11224         rsurface.modellightmapcolor4f  = color4f;
11225         rsurface.modellightmapcolor4f_vertexbuffer = 0;
11226         rsurface.modellightmapcolor4f_bufferoffset = 0;
11227         rsurface.modeltexcoordtexture2f  = texcoord2f;
11228         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11229         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11230         rsurface.modeltexcoordlightmap2f  = NULL;
11231         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11232         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11233         rsurface.modelelement3i = element3i;
11234         rsurface.modelelement3i_indexbuffer = NULL;
11235         rsurface.modelelement3i_bufferoffset = 0;
11236         rsurface.modelelement3s = element3s;
11237         rsurface.modelelement3s_indexbuffer = NULL;
11238         rsurface.modelelement3s_bufferoffset = 0;
11239         rsurface.modellightmapoffsets = NULL;
11240         rsurface.modelsurfaces = NULL;
11241         rsurface.batchgeneratedvertex = false;
11242         rsurface.batchfirstvertex = 0;
11243         rsurface.batchnumvertices = 0;
11244         rsurface.batchfirsttriangle = 0;
11245         rsurface.batchnumtriangles = 0;
11246         rsurface.batchvertex3f  = NULL;
11247         rsurface.batchvertex3f_vertexbuffer = NULL;
11248         rsurface.batchvertex3f_bufferoffset = 0;
11249         rsurface.batchsvector3f = NULL;
11250         rsurface.batchsvector3f_vertexbuffer = NULL;
11251         rsurface.batchsvector3f_bufferoffset = 0;
11252         rsurface.batchtvector3f = NULL;
11253         rsurface.batchtvector3f_vertexbuffer = NULL;
11254         rsurface.batchtvector3f_bufferoffset = 0;
11255         rsurface.batchnormal3f  = NULL;
11256         rsurface.batchnormal3f_vertexbuffer = NULL;
11257         rsurface.batchnormal3f_bufferoffset = 0;
11258         rsurface.batchlightmapcolor4f = NULL;
11259         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11260         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11261         rsurface.batchtexcoordtexture2f = NULL;
11262         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11263         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11264         rsurface.batchtexcoordlightmap2f = NULL;
11265         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11266         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11267         rsurface.batchvertexmesh = NULL;
11268         rsurface.batchvertexmeshbuffer = NULL;
11269         rsurface.batchvertexposition = NULL;
11270         rsurface.batchvertexpositionbuffer = NULL;
11271         rsurface.batchelement3i = NULL;
11272         rsurface.batchelement3i_indexbuffer = NULL;
11273         rsurface.batchelement3i_bufferoffset = 0;
11274         rsurface.batchelement3s = NULL;
11275         rsurface.batchelement3s_indexbuffer = NULL;
11276         rsurface.batchelement3s_bufferoffset = 0;
11277         rsurface.passcolor4f = NULL;
11278         rsurface.passcolor4f_vertexbuffer = NULL;
11279         rsurface.passcolor4f_bufferoffset = 0;
11280
11281         if (rsurface.modelnumvertices && rsurface.modelelement3i)
11282         {
11283                 if ((wantnormals || wanttangents) && !normal3f)
11284                 {
11285                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11286                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11287                 }
11288                 if (wanttangents && !svector3f)
11289                 {
11290                         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);
11291                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11292                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11293                 }
11294         }
11295
11296         // now convert arrays into vertexmesh structs
11297         for (i = 0;i < numvertices;i++)
11298         {
11299                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
11300                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
11301                 if (rsurface.modelsvector3f)
11302                         VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
11303                 if (rsurface.modeltvector3f)
11304                         VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
11305                 if (rsurface.modelnormal3f)
11306                         VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
11307                 if (rsurface.modellightmapcolor4f)
11308                         Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
11309                 if (rsurface.modeltexcoordtexture2f)
11310                         Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
11311                 if (rsurface.modeltexcoordlightmap2f)
11312                         Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
11313         }
11314 }
11315
11316 float RSurf_FogPoint(const float *v)
11317 {
11318         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11319         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11320         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11321         float FogHeightFade = r_refdef.fogheightfade;
11322         float fogfrac;
11323         unsigned int fogmasktableindex;
11324         if (r_refdef.fogplaneviewabove)
11325                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11326         else
11327                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11328         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11329         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11330 }
11331
11332 float RSurf_FogVertex(const float *v)
11333 {
11334         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11335         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11336         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11337         float FogHeightFade = rsurface.fogheightfade;
11338         float fogfrac;
11339         unsigned int fogmasktableindex;
11340         if (r_refdef.fogplaneviewabove)
11341                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11342         else
11343                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11344         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11345         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11346 }
11347
11348 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11349 {
11350         int i;
11351         for (i = 0;i < numelements;i++)
11352                 outelement3i[i] = inelement3i[i] + adjust;
11353 }
11354
11355 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11356 extern cvar_t gl_vbo;
11357 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11358 {
11359         int deformindex;
11360         int firsttriangle;
11361         int numtriangles;
11362         int firstvertex;
11363         int endvertex;
11364         int numvertices;
11365         int surfacefirsttriangle;
11366         int surfacenumtriangles;
11367         int surfacefirstvertex;
11368         int surfaceendvertex;
11369         int surfacenumvertices;
11370         int needsupdate;
11371         int i, j;
11372         qboolean gaps;
11373         qboolean dynamicvertex;
11374         float amplitude;
11375         float animpos;
11376         float scale;
11377         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11378         float waveparms[4];
11379         q3shaderinfo_deform_t *deform;
11380         const msurface_t *surface, *firstsurface;
11381         r_vertexposition_t *vertexposition;
11382         r_vertexmesh_t *vertexmesh;
11383         if (!texturenumsurfaces)
11384                 return;
11385         // find vertex range of this surface batch
11386         gaps = false;
11387         firstsurface = texturesurfacelist[0];
11388         firsttriangle = firstsurface->num_firsttriangle;
11389         numtriangles = 0;
11390         firstvertex = endvertex = firstsurface->num_firstvertex;
11391         for (i = 0;i < texturenumsurfaces;i++)
11392         {
11393                 surface = texturesurfacelist[i];
11394                 if (surface != firstsurface + i)
11395                         gaps = true;
11396                 surfacefirstvertex = surface->num_firstvertex;
11397                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11398                 surfacenumtriangles = surface->num_triangles;
11399                 if (firstvertex > surfacefirstvertex)
11400                         firstvertex = surfacefirstvertex;
11401                 if (endvertex < surfaceendvertex)
11402                         endvertex = surfaceendvertex;
11403                 numtriangles += surfacenumtriangles;
11404         }
11405
11406         // we now know the vertex range used, and if there are any gaps in it
11407         rsurface.batchfirstvertex = firstvertex;
11408         rsurface.batchnumvertices = endvertex - firstvertex;
11409         rsurface.batchfirsttriangle = firsttriangle;
11410         rsurface.batchnumtriangles = numtriangles;
11411
11412         // this variable holds flags for which properties have been updated that
11413         // may require regenerating vertexmesh or vertexposition arrays...
11414         needsupdate = 0;
11415
11416         // check if any dynamic vertex processing must occur
11417         dynamicvertex = false;
11418
11419         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11420                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11421         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11422         {
11423                 switch (deform->deform)
11424                 {
11425                 default:
11426                 case Q3DEFORM_PROJECTIONSHADOW:
11427                 case Q3DEFORM_TEXT0:
11428                 case Q3DEFORM_TEXT1:
11429                 case Q3DEFORM_TEXT2:
11430                 case Q3DEFORM_TEXT3:
11431                 case Q3DEFORM_TEXT4:
11432                 case Q3DEFORM_TEXT5:
11433                 case Q3DEFORM_TEXT6:
11434                 case Q3DEFORM_TEXT7:
11435                 case Q3DEFORM_NONE:
11436                         break;
11437                 case Q3DEFORM_AUTOSPRITE:
11438                         dynamicvertex = true;
11439                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11440                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11441                         break;
11442                 case Q3DEFORM_AUTOSPRITE2:
11443                         dynamicvertex = true;
11444                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11445                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11446                         break;
11447                 case Q3DEFORM_NORMAL:
11448                         dynamicvertex = true;
11449                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11450                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11451                         break;
11452                 case Q3DEFORM_WAVE:
11453                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11454                                 break; // if wavefunc is a nop, ignore this transform
11455                         dynamicvertex = true;
11456                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11457                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11458                         break;
11459                 case Q3DEFORM_BULGE:
11460                         dynamicvertex = true;
11461                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11462                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11463                         break;
11464                 case Q3DEFORM_MOVE:
11465                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11466                                 break; // if wavefunc is a nop, ignore this transform
11467                         dynamicvertex = true;
11468                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11469                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11470                         break;
11471                 }
11472         }
11473         switch(rsurface.texture->tcgen.tcgen)
11474         {
11475         default:
11476         case Q3TCGEN_TEXTURE:
11477                 break;
11478         case Q3TCGEN_LIGHTMAP:
11479                 dynamicvertex = true;
11480                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11481                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11482                 break;
11483         case Q3TCGEN_VECTOR:
11484                 dynamicvertex = true;
11485                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11486                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11487                 break;
11488         case Q3TCGEN_ENVIRONMENT:
11489                 dynamicvertex = true;
11490                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11491                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11492                 break;
11493         }
11494         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11495         {
11496                 dynamicvertex = true;
11497                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11498                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11499         }
11500
11501         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11502         {
11503                 dynamicvertex = true;
11504                 batchneed |= BATCHNEED_NOGAPS;
11505                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11506         }
11507
11508         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11509         {
11510                 dynamicvertex = true;
11511                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11512                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11513         }
11514
11515         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11516         {
11517                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11518                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11519                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11520                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11521                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11522                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11523                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11524         }
11525
11526         // when the model data has no vertex buffer (dynamic mesh), we need to
11527         // eliminate gaps
11528         if (!rsurface.modelvertexmeshbuffer)
11529                 batchneed |= BATCHNEED_NOGAPS;
11530
11531         // if needsupdate, we have to do a dynamic vertex batch for sure
11532         if (needsupdate & batchneed)
11533                 dynamicvertex = true;
11534
11535         // see if we need to build vertexmesh from arrays
11536         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11537                 dynamicvertex = true;
11538
11539         // see if we need to build vertexposition from arrays
11540         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11541                 dynamicvertex = true;
11542
11543         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11544         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11545                 dynamicvertex = true;
11546
11547         // if there is a chance of animated vertex colors, it's a dynamic batch
11548         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11549                 dynamicvertex = true;
11550
11551         rsurface.batchvertex3f = rsurface.modelvertex3f;
11552         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11553         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11554         rsurface.batchsvector3f = rsurface.modelsvector3f;
11555         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11556         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11557         rsurface.batchtvector3f = rsurface.modeltvector3f;
11558         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11559         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11560         rsurface.batchnormal3f = rsurface.modelnormal3f;
11561         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11562         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11563         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11564         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11565         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11566         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11567         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11568         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11569         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11570         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11571         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11572         rsurface.batchvertexposition = rsurface.modelvertexposition;
11573         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11574         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11575         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11576         rsurface.batchelement3i = rsurface.modelelement3i;
11577         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11578         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11579         rsurface.batchelement3s = rsurface.modelelement3s;
11580         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11581         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11582
11583         // if any dynamic vertex processing has to occur in software, we copy the
11584         // entire surface list together before processing to rebase the vertices
11585         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11586         //
11587         // if any gaps exist and we do not have a static vertex buffer, we have to
11588         // copy the surface list together to avoid wasting upload bandwidth on the
11589         // vertices in the gaps.
11590         //
11591         // if gaps exist and we have a static vertex buffer, we still have to
11592         // combine the index buffer ranges into one dynamic index buffer.
11593         //
11594         // in all cases we end up with data that can be drawn in one call.
11595
11596         if (!dynamicvertex)
11597         {
11598                 // static vertex data, just set pointers...
11599                 rsurface.batchgeneratedvertex = false;
11600                 // if there are gaps, we want to build a combined index buffer,
11601                 // otherwise use the original static buffer with an appropriate offset
11602                 if (gaps)
11603                 {
11604                         firsttriangle = 0;
11605                         numtriangles = 0;
11606                         for (i = 0;i < texturenumsurfaces;i++)
11607                         {
11608                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11609                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11610                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11611                                 numtriangles += surfacenumtriangles;
11612                         }
11613                         rsurface.batchelement3i = rsurface.array_batchelement3i;
11614                         rsurface.batchelement3i_indexbuffer = NULL;
11615                         rsurface.batchelement3i_bufferoffset = 0;
11616                         rsurface.batchelement3s = NULL;
11617                         rsurface.batchelement3s_indexbuffer = NULL;
11618                         rsurface.batchelement3s_bufferoffset = 0;
11619                         if (endvertex <= 65536)
11620                         {
11621                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
11622                                 for (i = 0;i < numtriangles*3;i++)
11623                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11624                         }
11625                         rsurface.batchfirsttriangle = firsttriangle;
11626                         rsurface.batchnumtriangles = numtriangles;
11627                 }
11628                 return;
11629         }
11630
11631         // something needs software processing, do it for real...
11632         // we only directly handle interleaved array data in this case...
11633         rsurface.batchgeneratedvertex = true;
11634
11635         // now copy the vertex data into a combined array and make an index array
11636         // (this is what Quake3 does all the time)
11637         //if (gaps || rsurface.batchfirstvertex)
11638         {
11639                 rsurface.batchvertexposition = NULL;
11640                 rsurface.batchvertexpositionbuffer = NULL;
11641                 rsurface.batchvertexmesh = NULL;
11642                 rsurface.batchvertexmeshbuffer = NULL;
11643                 rsurface.batchvertex3f = NULL;
11644                 rsurface.batchvertex3f_vertexbuffer = NULL;
11645                 rsurface.batchvertex3f_bufferoffset = 0;
11646                 rsurface.batchsvector3f = NULL;
11647                 rsurface.batchsvector3f_vertexbuffer = NULL;
11648                 rsurface.batchsvector3f_bufferoffset = 0;
11649                 rsurface.batchtvector3f = NULL;
11650                 rsurface.batchtvector3f_vertexbuffer = NULL;
11651                 rsurface.batchtvector3f_bufferoffset = 0;
11652                 rsurface.batchnormal3f = NULL;
11653                 rsurface.batchnormal3f_vertexbuffer = NULL;
11654                 rsurface.batchnormal3f_bufferoffset = 0;
11655                 rsurface.batchlightmapcolor4f = NULL;
11656                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11657                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11658                 rsurface.batchtexcoordtexture2f = NULL;
11659                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11660                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11661                 rsurface.batchtexcoordlightmap2f = NULL;
11662                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11663                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11664                 rsurface.batchelement3i = rsurface.array_batchelement3i;
11665                 rsurface.batchelement3i_indexbuffer = NULL;
11666                 rsurface.batchelement3i_bufferoffset = 0;
11667                 rsurface.batchelement3s = NULL;
11668                 rsurface.batchelement3s_indexbuffer = NULL;
11669                 rsurface.batchelement3s_bufferoffset = 0;
11670                 // we'll only be setting up certain arrays as needed
11671                 if (batchneed & BATCHNEED_VERTEXPOSITION)
11672                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11673                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11674                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11675                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11676                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11677                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11678                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11679                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11680                 {
11681                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11682                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11683                 }
11684                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11685                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11686                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11687                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11688                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11689                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11690                 numvertices = 0;
11691                 numtriangles = 0;
11692                 for (i = 0;i < texturenumsurfaces;i++)
11693                 {
11694                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11695                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11696                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11697                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11698                         // copy only the data requested
11699                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11700                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11701                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11702                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11703                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11704                         {
11705                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11706                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11707                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11708                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11709                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11710                                 {
11711                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11712                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11713                                 }
11714                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11715                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11716                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11717                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11718                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11719                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11720                         }
11721                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11722                         numvertices += surfacenumvertices;
11723                         numtriangles += surfacenumtriangles;
11724                 }
11725
11726                 // generate a 16bit index array as well if possible
11727                 // (in general, dynamic batches fit)
11728                 if (numvertices <= 65536)
11729                 {
11730                         rsurface.batchelement3s = rsurface.array_batchelement3s;
11731                         for (i = 0;i < numtriangles*3;i++)
11732                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11733                 }
11734
11735                 // since we've copied everything, the batch now starts at 0
11736                 rsurface.batchfirstvertex = 0;
11737                 rsurface.batchnumvertices = numvertices;
11738                 rsurface.batchfirsttriangle = 0;
11739                 rsurface.batchnumtriangles = numtriangles;
11740         }
11741
11742         // q1bsp surfaces rendered in vertex color mode have to have colors
11743         // calculated based on lightstyles
11744         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11745         {
11746                 // generate color arrays for the surfaces in this list
11747                 int c[4];
11748                 int scale;
11749                 int size3;
11750                 const int *offsets;
11751                 const unsigned char *lm;
11752                 numvertices = 0;
11753                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11754                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11755                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11756                 for (i = 0;i < texturenumsurfaces;i++)
11757                 {
11758                         surface = texturesurfacelist[i];
11759                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11760                         surfacenumvertices = surface->num_vertices;
11761                         if (surface->lightmapinfo->samples)
11762                         {
11763                                 for (j = 0;j < surfacenumvertices;j++)
11764                                 {
11765                                         lm = surface->lightmapinfo->samples + offsets[j];
11766                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11767                                         VectorScale(lm, scale, c);
11768                                         if (surface->lightmapinfo->styles[1] != 255)
11769                                         {
11770                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11771                                                 lm += size3;
11772                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11773                                                 VectorMA(c, scale, lm, c);
11774                                                 if (surface->lightmapinfo->styles[2] != 255)
11775                                                 {
11776                                                         lm += size3;
11777                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11778                                                         VectorMA(c, scale, lm, c);
11779                                                         if (surface->lightmapinfo->styles[3] != 255)
11780                                                         {
11781                                                                 lm += size3;
11782                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11783                                                                 VectorMA(c, scale, lm, c);
11784                                                         }
11785                                                 }
11786                                         }
11787                                         c[0] >>= 15;
11788                                         c[1] >>= 15;
11789                                         c[2] >>= 15;
11790                                         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);
11791                                         numvertices++;
11792                                 }
11793                         }
11794                         else
11795                         {
11796                                 for (j = 0;j < surfacenumvertices;j++)
11797                                 {
11798                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11799                                         numvertices++;
11800                                 }
11801                         }
11802                 }
11803         }
11804
11805         // if vertices are deformed (sprite flares and things in maps, possibly
11806         // water waves, bulges and other deformations), modify the copied vertices
11807         // in place
11808         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11809         {
11810                 switch (deform->deform)
11811                 {
11812                 default:
11813                 case Q3DEFORM_PROJECTIONSHADOW:
11814                 case Q3DEFORM_TEXT0:
11815                 case Q3DEFORM_TEXT1:
11816                 case Q3DEFORM_TEXT2:
11817                 case Q3DEFORM_TEXT3:
11818                 case Q3DEFORM_TEXT4:
11819                 case Q3DEFORM_TEXT5:
11820                 case Q3DEFORM_TEXT6:
11821                 case Q3DEFORM_TEXT7:
11822                 case Q3DEFORM_NONE:
11823                         break;
11824                 case Q3DEFORM_AUTOSPRITE:
11825                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11826                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11827                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11828                         VectorNormalize(newforward);
11829                         VectorNormalize(newright);
11830                         VectorNormalize(newup);
11831                         // a single autosprite surface can contain multiple sprites...
11832                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11833                         {
11834                                 VectorClear(center);
11835                                 for (i = 0;i < 4;i++)
11836                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11837                                 VectorScale(center, 0.25f, center);
11838                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11839                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11840                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11841                                 for (i = 0;i < 4;i++)
11842                                 {
11843                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11844                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11845                                 }
11846                         }
11847                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11848                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11849                         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);
11850                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11851                         rsurface.batchvertex3f_vertexbuffer = NULL;
11852                         rsurface.batchvertex3f_bufferoffset = 0;
11853                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11854                         rsurface.batchsvector3f_vertexbuffer = NULL;
11855                         rsurface.batchsvector3f_bufferoffset = 0;
11856                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11857                         rsurface.batchtvector3f_vertexbuffer = NULL;
11858                         rsurface.batchtvector3f_bufferoffset = 0;
11859                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11860                         rsurface.batchnormal3f_vertexbuffer = NULL;
11861                         rsurface.batchnormal3f_bufferoffset = 0;
11862                         break;
11863                 case Q3DEFORM_AUTOSPRITE2:
11864                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11865                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11866                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11867                         VectorNormalize(newforward);
11868                         VectorNormalize(newright);
11869                         VectorNormalize(newup);
11870                         {
11871                                 const float *v1, *v2;
11872                                 vec3_t start, end;
11873                                 float f, l;
11874                                 struct
11875                                 {
11876                                         float length2;
11877                                         const float *v1;
11878                                         const float *v2;
11879                                 }
11880                                 shortest[2];
11881                                 memset(shortest, 0, sizeof(shortest));
11882                                 // a single autosprite surface can contain multiple sprites...
11883                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11884                                 {
11885                                         VectorClear(center);
11886                                         for (i = 0;i < 4;i++)
11887                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11888                                         VectorScale(center, 0.25f, center);
11889                                         // find the two shortest edges, then use them to define the
11890                                         // axis vectors for rotating around the central axis
11891                                         for (i = 0;i < 6;i++)
11892                                         {
11893                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11894                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11895                                                 l = VectorDistance2(v1, v2);
11896                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11897                                                 if (v1[2] != v2[2])
11898                                                         l += (1.0f / 1024.0f);
11899                                                 if (shortest[0].length2 > l || i == 0)
11900                                                 {
11901                                                         shortest[1] = shortest[0];
11902                                                         shortest[0].length2 = l;
11903                                                         shortest[0].v1 = v1;
11904                                                         shortest[0].v2 = v2;
11905                                                 }
11906                                                 else if (shortest[1].length2 > l || i == 1)
11907                                                 {
11908                                                         shortest[1].length2 = l;
11909                                                         shortest[1].v1 = v1;
11910                                                         shortest[1].v2 = v2;
11911                                                 }
11912                                         }
11913                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11914                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11915                                         // this calculates the right vector from the shortest edge
11916                                         // and the up vector from the edge midpoints
11917                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11918                                         VectorNormalize(right);
11919                                         VectorSubtract(end, start, up);
11920                                         VectorNormalize(up);
11921                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11922                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11923                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11924                                         VectorNegate(forward, forward);
11925                                         VectorReflect(forward, 0, up, forward);
11926                                         VectorNormalize(forward);
11927                                         CrossProduct(up, forward, newright);
11928                                         VectorNormalize(newright);
11929                                         // rotate the quad around the up axis vector, this is made
11930                                         // especially easy by the fact we know the quad is flat,
11931                                         // so we only have to subtract the center position and
11932                                         // measure distance along the right vector, and then
11933                                         // multiply that by the newright vector and add back the
11934                                         // center position
11935                                         // we also need to subtract the old position to undo the
11936                                         // displacement from the center, which we do with a
11937                                         // DotProduct, the subtraction/addition of center is also
11938                                         // optimized into DotProducts here
11939                                         l = DotProduct(right, center);
11940                                         for (i = 0;i < 4;i++)
11941                                         {
11942                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11943                                                 f = DotProduct(right, v1) - l;
11944                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11945                                         }
11946                                 }
11947                         }
11948                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11949                         rsurface.batchvertex3f_vertexbuffer = NULL;
11950                         rsurface.batchvertex3f_bufferoffset = 0;
11951                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11952                         {
11953                                 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11954                                 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11955                                 rsurface.batchnormal3f_vertexbuffer = NULL;
11956                                 rsurface.batchnormal3f_bufferoffset = 0;
11957                         }
11958                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11959                         {
11960                                 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);
11961                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11962                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11963                                 rsurface.batchsvector3f_bufferoffset = 0;
11964                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11965                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11966                                 rsurface.batchtvector3f_bufferoffset = 0;
11967                         }
11968                         break;
11969                 case Q3DEFORM_NORMAL:
11970                         // deform the normals to make reflections wavey
11971                         for (j = 0;j < rsurface.batchnumvertices;j++)
11972                         {
11973                                 float vertex[3];
11974                                 float *normal = rsurface.array_batchnormal3f + 3*j;
11975                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11976                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11977                                 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]);
11978                                 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]);
11979                                 VectorNormalize(normal);
11980                         }
11981                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11982                         rsurface.batchnormal3f_vertexbuffer = NULL;
11983                         rsurface.batchnormal3f_bufferoffset = 0;
11984                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11985                         {
11986                                 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);
11987                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11988                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11989                                 rsurface.batchsvector3f_bufferoffset = 0;
11990                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11991                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11992                                 rsurface.batchtvector3f_bufferoffset = 0;
11993                         }
11994                         break;
11995                 case Q3DEFORM_WAVE:
11996                         // deform vertex array to make wavey water and flags and such
11997                         waveparms[0] = deform->waveparms[0];
11998                         waveparms[1] = deform->waveparms[1];
11999                         waveparms[2] = deform->waveparms[2];
12000                         waveparms[3] = deform->waveparms[3];
12001                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
12002                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12003                         // this is how a divisor of vertex influence on deformation
12004                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
12005                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12006                         for (j = 0;j < rsurface.batchnumvertices;j++)
12007                         {
12008                                 // if the wavefunc depends on time, evaluate it per-vertex
12009                                 if (waveparms[3])
12010                                 {
12011                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
12012                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12013                                 }
12014                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
12015                         }
12016                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12017                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
12018                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12019                         rsurface.batchvertex3f_vertexbuffer = NULL;
12020                         rsurface.batchvertex3f_bufferoffset = 0;
12021                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12022                         rsurface.batchnormal3f_vertexbuffer = NULL;
12023                         rsurface.batchnormal3f_bufferoffset = 0;
12024                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12025                         {
12026                                 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);
12027                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12028                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12029                                 rsurface.batchsvector3f_bufferoffset = 0;
12030                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12031                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12032                                 rsurface.batchtvector3f_bufferoffset = 0;
12033                         }
12034                         break;
12035                 case Q3DEFORM_BULGE:
12036                         // deform vertex array to make the surface have moving bulges
12037                         for (j = 0;j < rsurface.batchnumvertices;j++)
12038                         {
12039                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
12040                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
12041                         }
12042                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12043                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
12044                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12045                         rsurface.batchvertex3f_vertexbuffer = NULL;
12046                         rsurface.batchvertex3f_bufferoffset = 0;
12047                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
12048                         rsurface.batchnormal3f_vertexbuffer = NULL;
12049                         rsurface.batchnormal3f_bufferoffset = 0;
12050                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12051                         {
12052                                 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);
12053                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
12054                                 rsurface.batchsvector3f_vertexbuffer = NULL;
12055                                 rsurface.batchsvector3f_bufferoffset = 0;
12056                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
12057                                 rsurface.batchtvector3f_vertexbuffer = NULL;
12058                                 rsurface.batchtvector3f_bufferoffset = 0;
12059                         }
12060                         break;
12061                 case Q3DEFORM_MOVE:
12062                         // deform vertex array
12063                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12064                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12065                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
12066                         VectorScale(deform->parms, scale, waveparms);
12067                         for (j = 0;j < rsurface.batchnumvertices;j++)
12068                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
12069                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12070                         rsurface.batchvertex3f_vertexbuffer = NULL;
12071                         rsurface.batchvertex3f_bufferoffset = 0;
12072                         break;
12073                 }
12074         }
12075
12076         // generate texcoords based on the chosen texcoord source
12077         switch(rsurface.texture->tcgen.tcgen)
12078         {
12079         default:
12080         case Q3TCGEN_TEXTURE:
12081                 break;
12082         case Q3TCGEN_LIGHTMAP:
12083                 if (rsurface.batchtexcoordlightmap2f)
12084                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
12085                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12086                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12087                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12088                 break;
12089         case Q3TCGEN_VECTOR:
12090                 for (j = 0;j < rsurface.batchnumvertices;j++)
12091                 {
12092                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12093                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12094                 }
12095                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12096                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12097                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12098                 break;
12099         case Q3TCGEN_ENVIRONMENT:
12100                 // make environment reflections using a spheremap
12101                 for (j = 0;j < rsurface.batchnumvertices;j++)
12102                 {
12103                         // identical to Q3A's method, but executed in worldspace so
12104                         // carried models can be shiny too
12105
12106                         float viewer[3], d, reflected[3], worldreflected[3];
12107
12108                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12109                         // VectorNormalize(viewer);
12110
12111                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12112
12113                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12114                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12115                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12116                         // note: this is proportinal to viewer, so we can normalize later
12117
12118                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12119                         VectorNormalize(worldreflected);
12120
12121                         // note: this sphere map only uses world x and z!
12122                         // so positive and negative y will LOOK THE SAME.
12123                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12124                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12125                 }
12126                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12127                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12128                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12129                 break;
12130         }
12131         // the only tcmod that needs software vertex processing is turbulent, so
12132         // check for it here and apply the changes if needed
12133         // and we only support that as the first one
12134         // (handling a mixture of turbulent and other tcmods would be problematic
12135         //  without punting it entirely to a software path)
12136         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12137         {
12138                 amplitude = rsurface.texture->tcmods[0].parms[1];
12139                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12140                 for (j = 0;j < rsurface.batchnumvertices;j++)
12141                 {
12142                         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);
12143                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12144                 }
12145                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12146                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12147                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12148         }
12149
12150         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12151         {
12152                 // convert the modified arrays to vertex structs
12153                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
12154                 rsurface.batchvertexmeshbuffer = NULL;
12155                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12156                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12157                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12158                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12159                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12160                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12161                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12162                 {
12163                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12164                         {
12165                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12166                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12167                         }
12168                 }
12169                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12170                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12171                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12172                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12173                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12174                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12175                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12176                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12177                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12178         }
12179
12180         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
12181         {
12182                 // convert the modified arrays to vertex structs
12183                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
12184                 rsurface.batchvertexpositionbuffer = NULL;
12185                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
12186                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
12187                 else
12188                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
12189                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
12190         }
12191 }
12192
12193 void RSurf_DrawBatch(void)
12194 {
12195 #if 0
12196         // batch debugging code
12197         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
12198         {
12199                 int i;
12200                 int j;
12201                 int c;
12202                 const int *e;
12203                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
12204                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
12205                 {
12206                         c = e[i];
12207                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
12208                         {
12209                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
12210                                 {
12211                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
12212                                                 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);
12213                                         break;
12214                                 }
12215                         }
12216                 }
12217         }
12218 #endif
12219         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);
12220 }
12221
12222 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12223 {
12224         // pick the closest matching water plane
12225         int planeindex, vertexindex, bestplaneindex = -1;
12226         float d, bestd;
12227         vec3_t vert;
12228         const float *v;
12229         r_waterstate_waterplane_t *p;
12230         bestd = 0;
12231         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12232         {
12233                 if(p->camera_entity != rsurface.texture->camera_entity)
12234                         continue;
12235                 d = 0;
12236                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
12237                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12238                 {
12239                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
12240                         d += fabs(PlaneDiff(vert, &p->plane));
12241                 }
12242                 if (bestd > d || bestplaneindex < 0)
12243                 {
12244                         bestd = d;
12245                         bestplaneindex = planeindex;
12246                 }
12247         }
12248         return bestplaneindex;
12249 }
12250
12251 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12252 {
12253         int i;
12254         for (i = 0;i < rsurface.batchnumvertices;i++)
12255                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12256         rsurface.passcolor4f = rsurface.array_passcolor4f;
12257         rsurface.passcolor4f_vertexbuffer = 0;
12258         rsurface.passcolor4f_bufferoffset = 0;
12259 }
12260
12261 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12262 {
12263         int i;
12264         float f;
12265         const float *v;
12266         const float *c;
12267         float *c2;
12268         if (rsurface.passcolor4f)
12269         {
12270                 // generate color arrays
12271                 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)
12272                 {
12273                         f = RSurf_FogVertex(v);
12274                         c2[0] = c[0] * f;
12275                         c2[1] = c[1] * f;
12276                         c2[2] = c[2] * f;
12277                         c2[3] = c[3];
12278                 }
12279         }
12280         else
12281         {
12282                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12283                 {
12284                         f = RSurf_FogVertex(v);
12285                         c2[0] = f;
12286                         c2[1] = f;
12287                         c2[2] = f;
12288                         c2[3] = 1;
12289                 }
12290         }
12291         rsurface.passcolor4f = rsurface.array_passcolor4f;
12292         rsurface.passcolor4f_vertexbuffer = 0;
12293         rsurface.passcolor4f_bufferoffset = 0;
12294 }
12295
12296 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12297 {
12298         int i;
12299         float f;
12300         const float *v;
12301         const float *c;
12302         float *c2;
12303         if (!rsurface.passcolor4f)
12304                 return;
12305         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)
12306         {
12307                 f = RSurf_FogVertex(v);
12308                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12309                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12310                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12311                 c2[3] = c[3];
12312         }
12313         rsurface.passcolor4f = rsurface.array_passcolor4f;
12314         rsurface.passcolor4f_vertexbuffer = 0;
12315         rsurface.passcolor4f_bufferoffset = 0;
12316 }
12317
12318 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12319 {
12320         int i;
12321         const float *c;
12322         float *c2;
12323         if (!rsurface.passcolor4f)
12324                 return;
12325         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12326         {
12327                 c2[0] = c[0] * r;
12328                 c2[1] = c[1] * g;
12329                 c2[2] = c[2] * b;
12330                 c2[3] = c[3] * a;
12331         }
12332         rsurface.passcolor4f = rsurface.array_passcolor4f;
12333         rsurface.passcolor4f_vertexbuffer = 0;
12334         rsurface.passcolor4f_bufferoffset = 0;
12335 }
12336
12337 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12338 {
12339         int i;
12340         const float *c;
12341         float *c2;
12342         if (!rsurface.passcolor4f)
12343                 return;
12344         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12345         {
12346                 c2[0] = c[0] + r_refdef.scene.ambient;
12347                 c2[1] = c[1] + r_refdef.scene.ambient;
12348                 c2[2] = c[2] + r_refdef.scene.ambient;
12349                 c2[3] = c[3];
12350         }
12351         rsurface.passcolor4f = rsurface.array_passcolor4f;
12352         rsurface.passcolor4f_vertexbuffer = 0;
12353         rsurface.passcolor4f_bufferoffset = 0;
12354 }
12355
12356 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12357 {
12358         // TODO: optimize
12359         rsurface.passcolor4f = NULL;
12360         rsurface.passcolor4f_vertexbuffer = 0;
12361         rsurface.passcolor4f_bufferoffset = 0;
12362         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12363         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12364         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12365         GL_Color(r, g, b, a);
12366         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12367         RSurf_DrawBatch();
12368 }
12369
12370 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12371 {
12372         // TODO: optimize applyfog && applycolor case
12373         // just apply fog if necessary, and tint the fog color array if necessary
12374         rsurface.passcolor4f = NULL;
12375         rsurface.passcolor4f_vertexbuffer = 0;
12376         rsurface.passcolor4f_bufferoffset = 0;
12377         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12378         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12379         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12380         GL_Color(r, g, b, a);
12381         RSurf_DrawBatch();
12382 }
12383
12384 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12385 {
12386         // TODO: optimize
12387         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12388         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12389         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12390         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12391         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12392         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12393         GL_Color(r, g, b, a);
12394         RSurf_DrawBatch();
12395 }
12396
12397 static void RSurf_DrawBatch_GL11_ClampColor(void)
12398 {
12399         int i;
12400         const float *c1;
12401         float *c2;
12402         if (!rsurface.passcolor4f)
12403                 return;
12404         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12405         {
12406                 c2[0] = bound(0.0f, c1[0], 1.0f);
12407                 c2[1] = bound(0.0f, c1[1], 1.0f);
12408                 c2[2] = bound(0.0f, c1[2], 1.0f);
12409                 c2[3] = bound(0.0f, c1[3], 1.0f);
12410         }
12411 }
12412
12413 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12414 {
12415         int i;
12416         float f;
12417         const float *v;
12418         const float *n;
12419         float *c;
12420         //vec3_t eyedir;
12421
12422         // fake shading
12423         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)
12424         {
12425                 f = -DotProduct(r_refdef.view.forward, n);
12426                 f = max(0, f);
12427                 f = f * 0.85 + 0.15; // work around so stuff won't get black
12428                 f *= r_refdef.lightmapintensity;
12429                 Vector4Set(c, f, f, f, 1);
12430         }
12431
12432         rsurface.passcolor4f = rsurface.array_passcolor4f;
12433         rsurface.passcolor4f_vertexbuffer = 0;
12434         rsurface.passcolor4f_bufferoffset = 0;
12435 }
12436
12437 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12438 {
12439         RSurf_DrawBatch_GL11_ApplyFakeLight();
12440         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12441         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12442         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12443         GL_Color(r, g, b, a);
12444         RSurf_DrawBatch();
12445 }
12446
12447 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12448 {
12449         int i;
12450         float f;
12451         float alpha;
12452         const float *v;
12453         const float *n;
12454         float *c;
12455         vec3_t ambientcolor;
12456         vec3_t diffusecolor;
12457         vec3_t lightdir;
12458         // TODO: optimize
12459         // model lighting
12460         VectorCopy(rsurface.modellight_lightdir, lightdir);
12461         f = 0.5f * r_refdef.lightmapintensity;
12462         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12463         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12464         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12465         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12466         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12467         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12468         alpha = *a;
12469         if (VectorLength2(diffusecolor) > 0)
12470         {
12471                 // q3-style directional shading
12472                 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)
12473                 {
12474                         if ((f = DotProduct(n, lightdir)) > 0)
12475                                 VectorMA(ambientcolor, f, diffusecolor, c);
12476                         else
12477                                 VectorCopy(ambientcolor, c);
12478                         c[3] = alpha;
12479                 }
12480                 *r = 1;
12481                 *g = 1;
12482                 *b = 1;
12483                 *a = 1;
12484                 rsurface.passcolor4f = rsurface.array_passcolor4f;
12485                 rsurface.passcolor4f_vertexbuffer = 0;
12486                 rsurface.passcolor4f_bufferoffset = 0;
12487                 *applycolor = false;
12488         }
12489         else
12490         {
12491                 *r = ambientcolor[0];
12492                 *g = ambientcolor[1];
12493                 *b = ambientcolor[2];
12494                 rsurface.passcolor4f = NULL;
12495                 rsurface.passcolor4f_vertexbuffer = 0;
12496                 rsurface.passcolor4f_bufferoffset = 0;
12497         }
12498 }
12499
12500 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12501 {
12502         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12503         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12504         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12505         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12506         GL_Color(r, g, b, a);
12507         RSurf_DrawBatch();
12508 }
12509
12510 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12511 {
12512         int i;
12513         float f;
12514         const float *v;
12515         float *c;
12516         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12517         {
12518                 f = 1 - RSurf_FogVertex(v);
12519                 c[0] = r;
12520                 c[1] = g;
12521                 c[2] = b;
12522                 c[3] = f * a;
12523         }
12524 }
12525
12526 void RSurf_SetupDepthAndCulling(void)
12527 {
12528         // submodels are biased to avoid z-fighting with world surfaces that they
12529         // may be exactly overlapping (avoids z-fighting artifacts on certain
12530         // doors and things in Quake maps)
12531         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12532         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12533         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12534         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12535 }
12536
12537 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12538 {
12539         // transparent sky would be ridiculous
12540         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12541                 return;
12542         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12543         skyrenderlater = true;
12544         RSurf_SetupDepthAndCulling();
12545         GL_DepthMask(true);
12546         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12547         // skymasking on them, and Quake3 never did sky masking (unlike
12548         // software Quake and software Quake2), so disable the sky masking
12549         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12550         // and skymasking also looks very bad when noclipping outside the
12551         // level, so don't use it then either.
12552         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12553         {
12554                 R_Mesh_ResetTextureState();
12555                 if (skyrendermasked)
12556                 {
12557                         R_SetupShader_DepthOrShadow();
12558                         // depth-only (masking)
12559                         GL_ColorMask(0,0,0,0);
12560                         // just to make sure that braindead drivers don't draw
12561                         // anything despite that colormask...
12562                         GL_BlendFunc(GL_ZERO, GL_ONE);
12563                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12564                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12565                 }
12566                 else
12567                 {
12568                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12569                         // fog sky
12570                         GL_BlendFunc(GL_ONE, GL_ZERO);
12571                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12572                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12573                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12574                 }
12575                 RSurf_DrawBatch();
12576                 if (skyrendermasked)
12577                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12578         }
12579         R_Mesh_ResetTextureState();
12580         GL_Color(1, 1, 1, 1);
12581 }
12582
12583 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12584 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12585 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12586 {
12587         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12588                 return;
12589         if (prepass)
12590         {
12591                 // render screenspace normalmap to texture
12592                 GL_DepthMask(true);
12593                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12594                 RSurf_DrawBatch();
12595                 return;
12596         }
12597
12598         // bind lightmap texture
12599
12600         // water/refraction/reflection/camera surfaces have to be handled specially
12601         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12602         {
12603                 int start, end, startplaneindex;
12604                 for (start = 0;start < texturenumsurfaces;start = end)
12605                 {
12606                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12607                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12608                                 ;
12609                         // now that we have a batch using the same planeindex, render it
12610                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12611                         {
12612                                 // render water or distortion background
12613                                 GL_DepthMask(true);
12614                                 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));
12615                                 RSurf_DrawBatch();
12616                                 // blend surface on top
12617                                 GL_DepthMask(false);
12618                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12619                                 RSurf_DrawBatch();
12620                         }
12621                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12622                         {
12623                                 // render surface with reflection texture as input
12624                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12625                                 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));
12626                                 RSurf_DrawBatch();
12627                         }
12628                 }
12629                 return;
12630         }
12631
12632         // render surface batch normally
12633         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12634         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12635         RSurf_DrawBatch();
12636 }
12637
12638 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12639 {
12640         // OpenGL 1.3 path - anything not completely ancient
12641         qboolean applycolor;
12642         qboolean applyfog;
12643         int layerindex;
12644         const texturelayer_t *layer;
12645         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);
12646         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12647
12648         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12649         {
12650                 vec4_t layercolor;
12651                 int layertexrgbscale;
12652                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12653                 {
12654                         if (layerindex == 0)
12655                                 GL_AlphaTest(true);
12656                         else
12657                         {
12658                                 GL_AlphaTest(false);
12659                                 GL_DepthFunc(GL_EQUAL);
12660                         }
12661                 }
12662                 GL_DepthMask(layer->depthmask && writedepth);
12663                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12664                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12665                 {
12666                         layertexrgbscale = 4;
12667                         VectorScale(layer->color, 0.25f, layercolor);
12668                 }
12669                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12670                 {
12671                         layertexrgbscale = 2;
12672                         VectorScale(layer->color, 0.5f, layercolor);
12673                 }
12674                 else
12675                 {
12676                         layertexrgbscale = 1;
12677                         VectorScale(layer->color, 1.0f, layercolor);
12678                 }
12679                 layercolor[3] = layer->color[3];
12680                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12681                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12682                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12683                 switch (layer->type)
12684                 {
12685                 case TEXTURELAYERTYPE_LITTEXTURE:
12686                         // single-pass lightmapped texture with 2x rgbscale
12687                         R_Mesh_TexBind(0, r_texture_white);
12688                         R_Mesh_TexMatrix(0, NULL);
12689                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12690                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12691                         R_Mesh_TexBind(1, layer->texture);
12692                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12693                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12694                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12695                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12696                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12697                         else if (FAKELIGHT_ENABLED)
12698                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12699                         else if (rsurface.uselightmaptexture)
12700                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12701                         else
12702                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12703                         break;
12704                 case TEXTURELAYERTYPE_TEXTURE:
12705                         // singletexture unlit texture with transparency support
12706                         R_Mesh_TexBind(0, layer->texture);
12707                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12708                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12709                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12710                         R_Mesh_TexBind(1, 0);
12711                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12712                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12713                         break;
12714                 case TEXTURELAYERTYPE_FOG:
12715                         // singletexture fogging
12716                         if (layer->texture)
12717                         {
12718                                 R_Mesh_TexBind(0, layer->texture);
12719                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12720                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12721                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12722                         }
12723                         else
12724                         {
12725                                 R_Mesh_TexBind(0, 0);
12726                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12727                         }
12728                         R_Mesh_TexBind(1, 0);
12729                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12730                         // generate a color array for the fog pass
12731                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12732                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12733                         RSurf_DrawBatch();
12734                         break;
12735                 default:
12736                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12737                 }
12738         }
12739         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12740         {
12741                 GL_DepthFunc(GL_LEQUAL);
12742                 GL_AlphaTest(false);
12743         }
12744 }
12745
12746 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12747 {
12748         // OpenGL 1.1 - crusty old voodoo path
12749         qboolean applyfog;
12750         int layerindex;
12751         const texturelayer_t *layer;
12752         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);
12753         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12754
12755         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12756         {
12757                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12758                 {
12759                         if (layerindex == 0)
12760                                 GL_AlphaTest(true);
12761                         else
12762                         {
12763                                 GL_AlphaTest(false);
12764                                 GL_DepthFunc(GL_EQUAL);
12765                         }
12766                 }
12767                 GL_DepthMask(layer->depthmask && writedepth);
12768                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12769                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12770                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12771                 switch (layer->type)
12772                 {
12773                 case TEXTURELAYERTYPE_LITTEXTURE:
12774                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12775                         {
12776                                 // two-pass lit texture with 2x rgbscale
12777                                 // first the lightmap pass
12778                                 R_Mesh_TexBind(0, r_texture_white);
12779                                 R_Mesh_TexMatrix(0, NULL);
12780                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12781                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12782                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12783                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12784                                 else if (FAKELIGHT_ENABLED)
12785                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12786                                 else if (rsurface.uselightmaptexture)
12787                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12788                                 else
12789                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12790                                 // then apply the texture to it
12791                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12792                                 R_Mesh_TexBind(0, layer->texture);
12793                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12794                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12795                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12796                                 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);
12797                         }
12798                         else
12799                         {
12800                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12801                                 R_Mesh_TexBind(0, layer->texture);
12802                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12803                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12804                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12805                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12806                                         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);
12807                                 else
12808                                         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);
12809                         }
12810                         break;
12811                 case TEXTURELAYERTYPE_TEXTURE:
12812                         // singletexture unlit texture with transparency support
12813                         R_Mesh_TexBind(0, layer->texture);
12814                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12815                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12816                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12817                         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);
12818                         break;
12819                 case TEXTURELAYERTYPE_FOG:
12820                         // singletexture fogging
12821                         if (layer->texture)
12822                         {
12823                                 R_Mesh_TexBind(0, layer->texture);
12824                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12825                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12826                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12827                         }
12828                         else
12829                         {
12830                                 R_Mesh_TexBind(0, 0);
12831                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12832                         }
12833                         // generate a color array for the fog pass
12834                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12835                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12836                         RSurf_DrawBatch();
12837                         break;
12838                 default:
12839                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12840                 }
12841         }
12842         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12843         {
12844                 GL_DepthFunc(GL_LEQUAL);
12845                 GL_AlphaTest(false);
12846         }
12847 }
12848
12849 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12850 {
12851         int vi;
12852         int j;
12853         r_vertexgeneric_t *batchvertex;
12854         float c[4];
12855
12856         GL_AlphaTest(false);
12857 //      R_Mesh_ResetTextureState();
12858         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12859
12860         if(rsurface.texture && rsurface.texture->currentskinframe)
12861         {
12862                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12863                 c[3] *= rsurface.texture->currentalpha;
12864         }
12865         else
12866         {
12867                 c[0] = 1;
12868                 c[1] = 0;
12869                 c[2] = 1;
12870                 c[3] = 1;
12871         }
12872
12873         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12874         {
12875                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12876                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12877                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12878         }
12879
12880         // brighten it up (as texture value 127 means "unlit")
12881         c[0] *= 2 * r_refdef.view.colorscale;
12882         c[1] *= 2 * r_refdef.view.colorscale;
12883         c[2] *= 2 * r_refdef.view.colorscale;
12884
12885         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12886                 c[3] *= r_wateralpha.value;
12887
12888         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12889         {
12890                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12891                 GL_DepthMask(false);
12892         }
12893         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12894         {
12895                 GL_BlendFunc(GL_ONE, GL_ONE);
12896                 GL_DepthMask(false);
12897         }
12898         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12899         {
12900                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12901                 GL_DepthMask(false);
12902         }
12903         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12904         {
12905                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12906                 GL_DepthMask(false);
12907         }
12908         else
12909         {
12910                 GL_BlendFunc(GL_ONE, GL_ZERO);
12911                 GL_DepthMask(writedepth);
12912         }
12913
12914         if (r_showsurfaces.integer == 3)
12915         {
12916                 rsurface.passcolor4f = NULL;
12917
12918                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12919                 {
12920                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12921
12922                         rsurface.passcolor4f = NULL;
12923                         rsurface.passcolor4f_vertexbuffer = 0;
12924                         rsurface.passcolor4f_bufferoffset = 0;
12925                 }
12926                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12927                 {
12928                         qboolean applycolor = true;
12929                         float one = 1.0;
12930
12931                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12932
12933                         r_refdef.lightmapintensity = 1;
12934                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12935                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12936                 }
12937                 else if (FAKELIGHT_ENABLED)
12938                 {
12939                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12940
12941                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
12942                         RSurf_DrawBatch_GL11_ApplyFakeLight();
12943                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12944                 }
12945                 else
12946                 {
12947                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12948
12949                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12950                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12951                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12952                 }
12953
12954                 if(!rsurface.passcolor4f)
12955                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12956
12957                 RSurf_DrawBatch_GL11_ApplyAmbient();
12958                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12959                 if(r_refdef.fogenabled)
12960                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12961                 RSurf_DrawBatch_GL11_ClampColor();
12962
12963                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12964                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12965                 RSurf_DrawBatch();
12966         }
12967         else if (!r_refdef.view.showdebug)
12968         {
12969                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12970                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12971                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12972                 {
12973                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12974                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12975                 }
12976                 R_Mesh_PrepareVertices_Generic_Unlock();
12977                 RSurf_DrawBatch();
12978         }
12979         else if (r_showsurfaces.integer == 4)
12980         {
12981                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12982                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12983                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12984                 {
12985                         unsigned char c = vi << 3;
12986                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12987                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12988                 }
12989                 R_Mesh_PrepareVertices_Generic_Unlock();
12990                 RSurf_DrawBatch();
12991         }
12992         else if (r_showsurfaces.integer == 2)
12993         {
12994                 const int *e;
12995                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12996                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12997                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12998                 {
12999                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
13000                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
13001                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
13002                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
13003                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
13004                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
13005                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
13006                 }
13007                 R_Mesh_PrepareVertices_Generic_Unlock();
13008                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
13009         }
13010         else
13011         {
13012                 int texturesurfaceindex;
13013                 int k;
13014                 const msurface_t *surface;
13015                 unsigned char surfacecolor4ub[4];
13016                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13017                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
13018                 vi = 0;
13019                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
13020                 {
13021                         surface = texturesurfacelist[texturesurfaceindex];
13022                         k = (int)(((size_t)surface) / sizeof(msurface_t));
13023                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
13024                         for (j = 0;j < surface->num_vertices;j++)
13025                         {
13026                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13027                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
13028                                 vi++;
13029                         }
13030                 }
13031                 R_Mesh_PrepareVertices_Generic_Unlock();
13032                 RSurf_DrawBatch();
13033         }
13034 }
13035
13036 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13037 {
13038         CHECKGLERROR
13039         RSurf_SetupDepthAndCulling();
13040         if (r_showsurfaces.integer)
13041         {
13042                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13043                 return;
13044         }
13045         switch (vid.renderpath)
13046         {
13047         case RENDERPATH_GL20:
13048         case RENDERPATH_CGGL:
13049         case RENDERPATH_D3D9:
13050         case RENDERPATH_D3D10:
13051         case RENDERPATH_D3D11:
13052                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13053                 break;
13054         case RENDERPATH_GL13:
13055                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13056                 break;
13057         case RENDERPATH_GL11:
13058                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13059                 break;
13060         }
13061         CHECKGLERROR
13062 }
13063
13064 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13065 {
13066         CHECKGLERROR
13067         RSurf_SetupDepthAndCulling();
13068         if (r_showsurfaces.integer)
13069         {
13070                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13071                 return;
13072         }
13073         switch (vid.renderpath)
13074         {
13075         case RENDERPATH_GL20:
13076         case RENDERPATH_CGGL:
13077         case RENDERPATH_D3D9:
13078         case RENDERPATH_D3D10:
13079         case RENDERPATH_D3D11:
13080                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13081                 break;
13082         case RENDERPATH_GL13:
13083                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13084                 break;
13085         case RENDERPATH_GL11:
13086                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13087                 break;
13088         }
13089         CHECKGLERROR
13090 }
13091
13092 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13093 {
13094         int i, j;
13095         int texturenumsurfaces, endsurface;
13096         texture_t *texture;
13097         const msurface_t *surface;
13098 #define MAXBATCH_TRANSPARENTSURFACES 256
13099         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13100
13101         // if the model is static it doesn't matter what value we give for
13102         // wantnormals and wanttangents, so this logic uses only rules applicable
13103         // to a model, knowing that they are meaningless otherwise
13104         if (ent == r_refdef.scene.worldentity)
13105                 RSurf_ActiveWorldEntity();
13106         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13107                 RSurf_ActiveModelEntity(ent, false, false, false);
13108         else
13109         {
13110                 switch (vid.renderpath)
13111                 {
13112                 case RENDERPATH_GL20:
13113                 case RENDERPATH_CGGL:
13114                 case RENDERPATH_D3D9:
13115                 case RENDERPATH_D3D10:
13116                 case RENDERPATH_D3D11:
13117                         RSurf_ActiveModelEntity(ent, true, true, false);
13118                         break;
13119                 case RENDERPATH_GL13:
13120                 case RENDERPATH_GL11:
13121                         RSurf_ActiveModelEntity(ent, true, false, false);
13122                         break;
13123                 }
13124         }
13125
13126         if (r_transparentdepthmasking.integer)
13127         {
13128                 qboolean setup = false;
13129                 for (i = 0;i < numsurfaces;i = j)
13130                 {
13131                         j = i + 1;
13132                         surface = rsurface.modelsurfaces + surfacelist[i];
13133                         texture = surface->texture;
13134                         rsurface.texture = R_GetCurrentTexture(texture);
13135                         rsurface.lightmaptexture = NULL;
13136                         rsurface.deluxemaptexture = NULL;
13137                         rsurface.uselightmaptexture = false;
13138                         // scan ahead until we find a different texture
13139                         endsurface = min(i + 1024, numsurfaces);
13140                         texturenumsurfaces = 0;
13141                         texturesurfacelist[texturenumsurfaces++] = surface;
13142                         for (;j < endsurface;j++)
13143                         {
13144                                 surface = rsurface.modelsurfaces + surfacelist[j];
13145                                 if (texture != surface->texture)
13146                                         break;
13147                                 texturesurfacelist[texturenumsurfaces++] = surface;
13148                         }
13149                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13150                                 continue;
13151                         // render the range of surfaces as depth
13152                         if (!setup)
13153                         {
13154                                 setup = true;
13155                                 GL_ColorMask(0,0,0,0);
13156                                 GL_Color(1,1,1,1);
13157                                 GL_DepthTest(true);
13158                                 GL_BlendFunc(GL_ONE, GL_ZERO);
13159                                 GL_DepthMask(true);
13160                                 GL_AlphaTest(false);
13161 //                              R_Mesh_ResetTextureState();
13162                                 R_SetupShader_DepthOrShadow();
13163                         }
13164                         RSurf_SetupDepthAndCulling();
13165                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13166                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13167                         RSurf_DrawBatch();
13168                 }
13169                 if (setup)
13170                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13171         }
13172
13173         for (i = 0;i < numsurfaces;i = j)
13174         {
13175                 j = i + 1;
13176                 surface = rsurface.modelsurfaces + surfacelist[i];
13177                 texture = surface->texture;
13178                 rsurface.texture = R_GetCurrentTexture(texture);
13179                 // scan ahead until we find a different texture
13180                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13181                 texturenumsurfaces = 0;
13182                 texturesurfacelist[texturenumsurfaces++] = surface;
13183                 if(FAKELIGHT_ENABLED)
13184                 {
13185                         rsurface.lightmaptexture = NULL;
13186                         rsurface.deluxemaptexture = NULL;
13187                         rsurface.uselightmaptexture = false;
13188                         for (;j < endsurface;j++)
13189                         {
13190                                 surface = rsurface.modelsurfaces + surfacelist[j];
13191                                 if (texture != surface->texture)
13192                                         break;
13193                                 texturesurfacelist[texturenumsurfaces++] = surface;
13194                         }
13195                 }
13196                 else
13197                 {
13198                         rsurface.lightmaptexture = surface->lightmaptexture;
13199                         rsurface.deluxemaptexture = surface->deluxemaptexture;
13200                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13201                         for (;j < endsurface;j++)
13202                         {
13203                                 surface = rsurface.modelsurfaces + surfacelist[j];
13204                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13205                                         break;
13206                                 texturesurfacelist[texturenumsurfaces++] = surface;
13207                         }
13208                 }
13209                 // render the range of surfaces
13210                 if (ent == r_refdef.scene.worldentity)
13211                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13212                 else
13213                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13214         }
13215         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13216         GL_AlphaTest(false);
13217 }
13218
13219 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13220 {
13221         // transparent surfaces get pushed off into the transparent queue
13222         int surfacelistindex;
13223         const msurface_t *surface;
13224         vec3_t tempcenter, center;
13225         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13226         {
13227                 surface = texturesurfacelist[surfacelistindex];
13228                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13229                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13230                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13231                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13232                 if (queueentity->transparent_offset) // transparent offset
13233                 {
13234                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13235                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13236                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13237                 }
13238                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13239         }
13240 }
13241
13242 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13243 {
13244         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13245                 return;
13246         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13247                 return;
13248         RSurf_SetupDepthAndCulling();
13249         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13250         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13251         RSurf_DrawBatch();
13252 }
13253
13254 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13255 {
13256         const entity_render_t *queueentity = r_refdef.scene.worldentity;
13257         CHECKGLERROR
13258         if (depthonly)
13259                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13260         else if (prepass)
13261         {
13262                 if (!rsurface.texture->currentnumlayers)
13263                         return;
13264                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13265                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13266                 else
13267                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13268         }
13269         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13270                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13271         else if (!rsurface.texture->currentnumlayers)
13272                 return;
13273         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13274         {
13275                 // in the deferred case, transparent surfaces were queued during prepass
13276                 if (!r_shadow_usingdeferredprepass)
13277                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13278         }
13279         else
13280         {
13281                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13282                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13283         }
13284         CHECKGLERROR
13285 }
13286
13287 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13288 {
13289         int i, j;
13290         texture_t *texture;
13291         // break the surface list down into batches by texture and use of lightmapping
13292         for (i = 0;i < numsurfaces;i = j)
13293         {
13294                 j = i + 1;
13295                 // texture is the base texture pointer, rsurface.texture is the
13296                 // current frame/skin the texture is directing us to use (for example
13297                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13298                 // use skin 1 instead)
13299                 texture = surfacelist[i]->texture;
13300                 rsurface.texture = R_GetCurrentTexture(texture);
13301                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13302                 {
13303                         // if this texture is not the kind we want, skip ahead to the next one
13304                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13305                                 ;
13306                         continue;
13307                 }
13308                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13309                 {
13310                         rsurface.lightmaptexture = NULL;
13311                         rsurface.deluxemaptexture = NULL;
13312                         rsurface.uselightmaptexture = false;
13313                         // simply scan ahead until we find a different texture or lightmap state
13314                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13315                                 ;
13316                 }
13317                 else
13318                 {
13319                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13320                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13321                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13322                         // simply scan ahead until we find a different texture or lightmap state
13323                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13324                                 ;
13325                 }
13326                 // render the range of surfaces
13327                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13328         }
13329 }
13330
13331 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13332 {
13333         CHECKGLERROR
13334         if (depthonly)
13335                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13336         else if (prepass)
13337         {
13338                 if (!rsurface.texture->currentnumlayers)
13339                         return;
13340                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13341                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13342                 else
13343                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13344         }
13345         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13346                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13347         else if (!rsurface.texture->currentnumlayers)
13348                 return;
13349         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13350         {
13351                 // in the deferred case, transparent surfaces were queued during prepass
13352                 if (!r_shadow_usingdeferredprepass)
13353                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13354         }
13355         else
13356         {
13357                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13358                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13359         }
13360         CHECKGLERROR
13361 }
13362
13363 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13364 {
13365         int i, j;
13366         texture_t *texture;
13367         // break the surface list down into batches by texture and use of lightmapping
13368         for (i = 0;i < numsurfaces;i = j)
13369         {
13370                 j = i + 1;
13371                 // texture is the base texture pointer, rsurface.texture is the
13372                 // current frame/skin the texture is directing us to use (for example
13373                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13374                 // use skin 1 instead)
13375                 texture = surfacelist[i]->texture;
13376                 rsurface.texture = R_GetCurrentTexture(texture);
13377                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13378                 {
13379                         // if this texture is not the kind we want, skip ahead to the next one
13380                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13381                                 ;
13382                         continue;
13383                 }
13384                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13385                 {
13386                         rsurface.lightmaptexture = NULL;
13387                         rsurface.deluxemaptexture = NULL;
13388                         rsurface.uselightmaptexture = false;
13389                         // simply scan ahead until we find a different texture or lightmap state
13390                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13391                                 ;
13392                 }
13393                 else
13394                 {
13395                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13396                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13397                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13398                         // simply scan ahead until we find a different texture or lightmap state
13399                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13400                                 ;
13401                 }
13402                 // render the range of surfaces
13403                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13404         }
13405 }
13406
13407 float locboxvertex3f[6*4*3] =
13408 {
13409         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13410         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13411         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13412         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13413         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13414         1,0,0, 0,0,0, 0,1,0, 1,1,0
13415 };
13416
13417 unsigned short locboxelements[6*2*3] =
13418 {
13419          0, 1, 2, 0, 2, 3,
13420          4, 5, 6, 4, 6, 7,
13421          8, 9,10, 8,10,11,
13422         12,13,14, 12,14,15,
13423         16,17,18, 16,18,19,
13424         20,21,22, 20,22,23
13425 };
13426
13427 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13428 {
13429         int i, j;
13430         cl_locnode_t *loc = (cl_locnode_t *)ent;
13431         vec3_t mins, size;
13432         float vertex3f[6*4*3];
13433         CHECKGLERROR
13434         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13435         GL_DepthMask(false);
13436         GL_DepthRange(0, 1);
13437         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13438         GL_DepthTest(true);
13439         GL_CullFace(GL_NONE);
13440         R_EntityMatrix(&identitymatrix);
13441
13442 //      R_Mesh_ResetTextureState();
13443
13444         i = surfacelist[0];
13445         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13446                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13447                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13448                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13449
13450         if (VectorCompare(loc->mins, loc->maxs))
13451         {
13452                 VectorSet(size, 2, 2, 2);
13453                 VectorMA(loc->mins, -0.5f, size, mins);
13454         }
13455         else
13456         {
13457                 VectorCopy(loc->mins, mins);
13458                 VectorSubtract(loc->maxs, loc->mins, size);
13459         }
13460
13461         for (i = 0;i < 6*4*3;)
13462                 for (j = 0;j < 3;j++, i++)
13463                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13464
13465         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13466         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13467         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13468 }
13469
13470 void R_DrawLocs(void)
13471 {
13472         int index;
13473         cl_locnode_t *loc, *nearestloc;
13474         vec3_t center;
13475         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13476         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13477         {
13478                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13479                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13480         }
13481 }
13482
13483 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13484 {
13485         if (decalsystem->decals)
13486                 Mem_Free(decalsystem->decals);
13487         memset(decalsystem, 0, sizeof(*decalsystem));
13488 }
13489
13490 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)
13491 {
13492         tridecal_t *decal;
13493         tridecal_t *decals;
13494         int i;
13495
13496         // expand or initialize the system
13497         if (decalsystem->maxdecals <= decalsystem->numdecals)
13498         {
13499                 decalsystem_t old = *decalsystem;
13500                 qboolean useshortelements;
13501                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13502                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13503                 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)));
13504                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13505                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13506                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13507                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13508                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13509                 if (decalsystem->numdecals)
13510                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13511                 if (old.decals)
13512                         Mem_Free(old.decals);
13513                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13514                         decalsystem->element3i[i] = i;
13515                 if (useshortelements)
13516                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13517                                 decalsystem->element3s[i] = i;
13518         }
13519
13520         // grab a decal and search for another free slot for the next one
13521         decals = decalsystem->decals;
13522         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13523         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13524                 ;
13525         decalsystem->freedecal = i;
13526         if (decalsystem->numdecals <= i)
13527                 decalsystem->numdecals = i + 1;
13528
13529         // initialize the decal
13530         decal->lived = 0;
13531         decal->triangleindex = triangleindex;
13532         decal->surfaceindex = surfaceindex;
13533         decal->decalsequence = decalsequence;
13534         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13535         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13536         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13537         decal->color4ub[0][3] = 255;
13538         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13539         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13540         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13541         decal->color4ub[1][3] = 255;
13542         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13543         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13544         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13545         decal->color4ub[2][3] = 255;
13546         decal->vertex3f[0][0] = v0[0];
13547         decal->vertex3f[0][1] = v0[1];
13548         decal->vertex3f[0][2] = v0[2];
13549         decal->vertex3f[1][0] = v1[0];
13550         decal->vertex3f[1][1] = v1[1];
13551         decal->vertex3f[1][2] = v1[2];
13552         decal->vertex3f[2][0] = v2[0];
13553         decal->vertex3f[2][1] = v2[1];
13554         decal->vertex3f[2][2] = v2[2];
13555         decal->texcoord2f[0][0] = t0[0];
13556         decal->texcoord2f[0][1] = t0[1];
13557         decal->texcoord2f[1][0] = t1[0];
13558         decal->texcoord2f[1][1] = t1[1];
13559         decal->texcoord2f[2][0] = t2[0];
13560         decal->texcoord2f[2][1] = t2[1];
13561 }
13562
13563 extern cvar_t cl_decals_bias;
13564 extern cvar_t cl_decals_models;
13565 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13566 // baseparms, parms, temps
13567 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)
13568 {
13569         int cornerindex;
13570         int index;
13571         float v[9][3];
13572         const float *vertex3f;
13573         int numpoints;
13574         float points[2][9][3];
13575         float temp[3];
13576         float tc[9][2];
13577         float f;
13578         float c[9][4];
13579         const int *e;
13580
13581         e = rsurface.modelelement3i + 3*triangleindex;
13582
13583         vertex3f = rsurface.modelvertex3f;
13584
13585         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13586         {
13587                 index = 3*e[cornerindex];
13588                 VectorCopy(vertex3f + index, v[cornerindex]);
13589         }
13590         // cull backfaces
13591         //TriangleNormal(v[0], v[1], v[2], normal);
13592         //if (DotProduct(normal, localnormal) < 0.0f)
13593         //      continue;
13594         // clip by each of the box planes formed from the projection matrix
13595         // if anything survives, we emit the decal
13596         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]);
13597         if (numpoints < 3)
13598                 return;
13599         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]);
13600         if (numpoints < 3)
13601                 return;
13602         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]);
13603         if (numpoints < 3)
13604                 return;
13605         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]);
13606         if (numpoints < 3)
13607                 return;
13608         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]);
13609         if (numpoints < 3)
13610                 return;
13611         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]);
13612         if (numpoints < 3)
13613                 return;
13614         // some part of the triangle survived, so we have to accept it...
13615         if (dynamic)
13616         {
13617                 // dynamic always uses the original triangle
13618                 numpoints = 3;
13619                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13620                 {
13621                         index = 3*e[cornerindex];
13622                         VectorCopy(vertex3f + index, v[cornerindex]);
13623                 }
13624         }
13625         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13626         {
13627                 // convert vertex positions to texcoords
13628                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13629                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13630                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13631                 // calculate distance fade from the projection origin
13632                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13633                 f = bound(0.0f, f, 1.0f);
13634                 c[cornerindex][0] = r * f;
13635                 c[cornerindex][1] = g * f;
13636                 c[cornerindex][2] = b * f;
13637                 c[cornerindex][3] = 1.0f;
13638                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13639         }
13640         if (dynamic)
13641                 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);
13642         else
13643                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13644                         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);
13645 }
13646 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)
13647 {
13648         matrix4x4_t projection;
13649         decalsystem_t *decalsystem;
13650         qboolean dynamic;
13651         dp_model_t *model;
13652         const msurface_t *surface;
13653         const msurface_t *surfaces;
13654         const int *surfacelist;
13655         const texture_t *texture;
13656         int numtriangles;
13657         int numsurfacelist;
13658         int surfacelistindex;
13659         int surfaceindex;
13660         int triangleindex;
13661         float localorigin[3];
13662         float localnormal[3];
13663         float localmins[3];
13664         float localmaxs[3];
13665         float localsize;
13666         //float normal[3];
13667         float planes[6][4];
13668         float angles[3];
13669         bih_t *bih;
13670         int bih_triangles_count;
13671         int bih_triangles[256];
13672         int bih_surfaces[256];
13673
13674         decalsystem = &ent->decalsystem;
13675         model = ent->model;
13676         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13677         {
13678                 R_DecalSystem_Reset(&ent->decalsystem);
13679                 return;
13680         }
13681
13682         if (!model->brush.data_leafs && !cl_decals_models.integer)
13683         {
13684                 if (decalsystem->model)
13685                         R_DecalSystem_Reset(decalsystem);
13686                 return;
13687         }
13688
13689         if (decalsystem->model != model)
13690                 R_DecalSystem_Reset(decalsystem);
13691         decalsystem->model = model;
13692
13693         RSurf_ActiveModelEntity(ent, false, false, false);
13694
13695         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13696         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13697         VectorNormalize(localnormal);
13698         localsize = worldsize*rsurface.inversematrixscale;
13699         localmins[0] = localorigin[0] - localsize;
13700         localmins[1] = localorigin[1] - localsize;
13701         localmins[2] = localorigin[2] - localsize;
13702         localmaxs[0] = localorigin[0] + localsize;
13703         localmaxs[1] = localorigin[1] + localsize;
13704         localmaxs[2] = localorigin[2] + localsize;
13705
13706         //VectorCopy(localnormal, planes[4]);
13707         //VectorVectors(planes[4], planes[2], planes[0]);
13708         AnglesFromVectors(angles, localnormal, NULL, false);
13709         AngleVectors(angles, planes[0], planes[2], planes[4]);
13710         VectorNegate(planes[0], planes[1]);
13711         VectorNegate(planes[2], planes[3]);
13712         VectorNegate(planes[4], planes[5]);
13713         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13714         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13715         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13716         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13717         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13718         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13719
13720 #if 1
13721 // works
13722 {
13723         matrix4x4_t forwardprojection;
13724         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13725         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13726 }
13727 #else
13728 // broken
13729 {
13730         float projectionvector[4][3];
13731         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13732         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13733         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13734         projectionvector[0][0] = planes[0][0] * ilocalsize;
13735         projectionvector[0][1] = planes[1][0] * ilocalsize;
13736         projectionvector[0][2] = planes[2][0] * ilocalsize;
13737         projectionvector[1][0] = planes[0][1] * ilocalsize;
13738         projectionvector[1][1] = planes[1][1] * ilocalsize;
13739         projectionvector[1][2] = planes[2][1] * ilocalsize;
13740         projectionvector[2][0] = planes[0][2] * ilocalsize;
13741         projectionvector[2][1] = planes[1][2] * ilocalsize;
13742         projectionvector[2][2] = planes[2][2] * ilocalsize;
13743         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13744         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13745         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13746         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13747 }
13748 #endif
13749
13750         dynamic = model->surfmesh.isanimated;
13751         numsurfacelist = model->nummodelsurfaces;
13752         surfacelist = model->sortedmodelsurfaces;
13753         surfaces = model->data_surfaces;
13754
13755         bih = NULL;
13756         bih_triangles_count = -1;
13757         if(!dynamic)
13758         {
13759                 if(model->render_bih.numleafs)
13760                         bih = &model->render_bih;
13761                 else if(model->collision_bih.numleafs)
13762                         bih = &model->collision_bih;
13763         }
13764         if(bih)
13765                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13766         if(bih_triangles_count == 0)
13767                 return;
13768         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13769                 return;
13770         if(bih_triangles_count > 0)
13771         {
13772                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13773                 {
13774                         surfaceindex = bih_surfaces[triangleindex];
13775                         surface = surfaces + surfaceindex;
13776                         texture = surface->texture;
13777                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13778                                 continue;
13779                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13780                                 continue;
13781                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13782                 }
13783         }
13784         else
13785         {
13786                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13787                 {
13788                         surfaceindex = surfacelist[surfacelistindex];
13789                         surface = surfaces + surfaceindex;
13790                         // check cull box first because it rejects more than any other check
13791                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13792                                 continue;
13793                         // skip transparent surfaces
13794                         texture = surface->texture;
13795                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13796                                 continue;
13797                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13798                                 continue;
13799                         numtriangles = surface->num_triangles;
13800                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13801                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13802                 }
13803         }
13804 }
13805
13806 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13807 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)
13808 {
13809         int renderentityindex;
13810         float worldmins[3];
13811         float worldmaxs[3];
13812         entity_render_t *ent;
13813
13814         if (!cl_decals_newsystem.integer)
13815                 return;
13816
13817         worldmins[0] = worldorigin[0] - worldsize;
13818         worldmins[1] = worldorigin[1] - worldsize;
13819         worldmins[2] = worldorigin[2] - worldsize;
13820         worldmaxs[0] = worldorigin[0] + worldsize;
13821         worldmaxs[1] = worldorigin[1] + worldsize;
13822         worldmaxs[2] = worldorigin[2] + worldsize;
13823
13824         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13825
13826         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13827         {
13828                 ent = r_refdef.scene.entities[renderentityindex];
13829                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13830                         continue;
13831
13832                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13833         }
13834 }
13835
13836 typedef struct r_decalsystem_splatqueue_s
13837 {
13838         vec3_t worldorigin;
13839         vec3_t worldnormal;
13840         float color[4];
13841         float tcrange[4];
13842         float worldsize;
13843         int decalsequence;
13844 }
13845 r_decalsystem_splatqueue_t;
13846
13847 int r_decalsystem_numqueued = 0;
13848 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13849
13850 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)
13851 {
13852         r_decalsystem_splatqueue_t *queue;
13853
13854         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13855                 return;
13856
13857         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13858         VectorCopy(worldorigin, queue->worldorigin);
13859         VectorCopy(worldnormal, queue->worldnormal);
13860         Vector4Set(queue->color, r, g, b, a);
13861         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13862         queue->worldsize = worldsize;
13863         queue->decalsequence = cl.decalsequence++;
13864 }
13865
13866 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13867 {
13868         int i;
13869         r_decalsystem_splatqueue_t *queue;
13870
13871         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13872                 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);
13873         r_decalsystem_numqueued = 0;
13874 }
13875
13876 extern cvar_t cl_decals_max;
13877 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13878 {
13879         int i;
13880         decalsystem_t *decalsystem = &ent->decalsystem;
13881         int numdecals;
13882         int killsequence;
13883         tridecal_t *decal;
13884         float frametime;
13885         float lifetime;
13886
13887         if (!decalsystem->numdecals)
13888                 return;
13889
13890         if (r_showsurfaces.integer)
13891                 return;
13892
13893         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13894         {
13895                 R_DecalSystem_Reset(decalsystem);
13896                 return;
13897         }
13898
13899         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13900         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13901
13902         if (decalsystem->lastupdatetime)
13903                 frametime = (cl.time - decalsystem->lastupdatetime);
13904         else
13905                 frametime = 0;
13906         decalsystem->lastupdatetime = cl.time;
13907         decal = decalsystem->decals;
13908         numdecals = decalsystem->numdecals;
13909
13910         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13911         {
13912                 if (decal->color4ub[0][3])
13913                 {
13914                         decal->lived += frametime;
13915                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13916                         {
13917                                 memset(decal, 0, sizeof(*decal));
13918                                 if (decalsystem->freedecal > i)
13919                                         decalsystem->freedecal = i;
13920                         }
13921                 }
13922         }
13923         decal = decalsystem->decals;
13924         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13925                 numdecals--;
13926
13927         // collapse the array by shuffling the tail decals into the gaps
13928         for (;;)
13929         {
13930                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13931                         decalsystem->freedecal++;
13932                 if (decalsystem->freedecal == numdecals)
13933                         break;
13934                 decal[decalsystem->freedecal] = decal[--numdecals];
13935         }
13936
13937         decalsystem->numdecals = numdecals;
13938
13939         if (numdecals <= 0)
13940         {
13941                 // if there are no decals left, reset decalsystem
13942                 R_DecalSystem_Reset(decalsystem);
13943         }
13944 }
13945
13946 extern skinframe_t *decalskinframe;
13947 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13948 {
13949         int i;
13950         decalsystem_t *decalsystem = &ent->decalsystem;
13951         int numdecals;
13952         tridecal_t *decal;
13953         float faderate;
13954         float alpha;
13955         float *v3f;
13956         float *c4f;
13957         float *t2f;
13958         const int *e;
13959         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13960         int numtris = 0;
13961
13962         numdecals = decalsystem->numdecals;
13963         if (!numdecals)
13964                 return;
13965
13966         if (r_showsurfaces.integer)
13967                 return;
13968
13969         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13970         {
13971                 R_DecalSystem_Reset(decalsystem);
13972                 return;
13973         }
13974
13975         // if the model is static it doesn't matter what value we give for
13976         // wantnormals and wanttangents, so this logic uses only rules applicable
13977         // to a model, knowing that they are meaningless otherwise
13978         if (ent == r_refdef.scene.worldentity)
13979                 RSurf_ActiveWorldEntity();
13980         else
13981                 RSurf_ActiveModelEntity(ent, false, false, false);
13982
13983         decalsystem->lastupdatetime = cl.time;
13984         decal = decalsystem->decals;
13985
13986         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13987
13988         // update vertex positions for animated models
13989         v3f = decalsystem->vertex3f;
13990         c4f = decalsystem->color4f;
13991         t2f = decalsystem->texcoord2f;
13992         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13993         {
13994                 if (!decal->color4ub[0][3])
13995                         continue;
13996
13997                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13998                         continue;
13999
14000                 // update color values for fading decals
14001                 if (decal->lived >= cl_decals_time.value)
14002                 {
14003                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
14004                         alpha *= (1.0f/255.0f);
14005                 }
14006                 else
14007                         alpha = 1.0f/255.0f;
14008
14009                 c4f[ 0] = decal->color4ub[0][0] * alpha;
14010                 c4f[ 1] = decal->color4ub[0][1] * alpha;
14011                 c4f[ 2] = decal->color4ub[0][2] * alpha;
14012                 c4f[ 3] = 1;
14013                 c4f[ 4] = decal->color4ub[1][0] * alpha;
14014                 c4f[ 5] = decal->color4ub[1][1] * alpha;
14015                 c4f[ 6] = decal->color4ub[1][2] * alpha;
14016                 c4f[ 7] = 1;
14017                 c4f[ 8] = decal->color4ub[2][0] * alpha;
14018                 c4f[ 9] = decal->color4ub[2][1] * alpha;
14019                 c4f[10] = decal->color4ub[2][2] * alpha;
14020                 c4f[11] = 1;
14021
14022                 t2f[0] = decal->texcoord2f[0][0];
14023                 t2f[1] = decal->texcoord2f[0][1];
14024                 t2f[2] = decal->texcoord2f[1][0];
14025                 t2f[3] = decal->texcoord2f[1][1];
14026                 t2f[4] = decal->texcoord2f[2][0];
14027                 t2f[5] = decal->texcoord2f[2][1];
14028
14029                 // update vertex positions for animated models
14030                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
14031                 {
14032                         e = rsurface.modelelement3i + 3*decal->triangleindex;
14033                         VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
14034                         VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
14035                         VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
14036                 }
14037                 else
14038                 {
14039                         VectorCopy(decal->vertex3f[0], v3f);
14040                         VectorCopy(decal->vertex3f[1], v3f + 3);
14041                         VectorCopy(decal->vertex3f[2], v3f + 6);
14042                 }
14043
14044                 if (r_refdef.fogenabled)
14045                 {
14046                         alpha = RSurf_FogVertex(v3f);
14047                         VectorScale(c4f, alpha, c4f);
14048                         alpha = RSurf_FogVertex(v3f + 3);
14049                         VectorScale(c4f + 4, alpha, c4f + 4);
14050                         alpha = RSurf_FogVertex(v3f + 6);
14051                         VectorScale(c4f + 8, alpha, c4f + 8);
14052                 }
14053
14054                 v3f += 9;
14055                 c4f += 12;
14056                 t2f += 6;
14057                 numtris++;
14058         }
14059
14060         if (numtris > 0)
14061         {
14062                 r_refdef.stats.drawndecals += numtris;
14063
14064                 // now render the decals all at once
14065                 // (this assumes they all use one particle font texture!)
14066                 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);
14067 //              R_Mesh_ResetTextureState();
14068                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
14069                 GL_DepthMask(false);
14070                 GL_DepthRange(0, 1);
14071                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
14072                 GL_DepthTest(true);
14073                 GL_CullFace(GL_NONE);
14074                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
14075                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
14076                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
14077         }
14078 }
14079
14080 static void R_DrawModelDecals(void)
14081 {
14082         int i, numdecals;
14083
14084         // fade faster when there are too many decals
14085         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14086         for (i = 0;i < r_refdef.scene.numentities;i++)
14087                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14088
14089         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
14090         for (i = 0;i < r_refdef.scene.numentities;i++)
14091                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14092                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14093
14094         R_DecalSystem_ApplySplatEntitiesQueue();
14095
14096         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14097         for (i = 0;i < r_refdef.scene.numentities;i++)
14098                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14099
14100         r_refdef.stats.totaldecals += numdecals;
14101
14102         if (r_showsurfaces.integer)
14103                 return;
14104
14105         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14106
14107         for (i = 0;i < r_refdef.scene.numentities;i++)
14108         {
14109                 if (!r_refdef.viewcache.entityvisible[i])
14110                         continue;
14111                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14112                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14113         }
14114 }
14115
14116 extern cvar_t mod_collision_bih;
14117 void R_DrawDebugModel(void)
14118 {
14119         entity_render_t *ent = rsurface.entity;
14120         int i, j, k, l, flagsmask;
14121         const msurface_t *surface;
14122         dp_model_t *model = ent->model;
14123         vec3_t v;
14124
14125         switch(vid.renderpath)
14126         {
14127         case RENDERPATH_GL11:
14128         case RENDERPATH_GL13:
14129         case RENDERPATH_GL20:
14130         case RENDERPATH_CGGL:
14131                 break;
14132         case RENDERPATH_D3D9:
14133                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14134                 return;
14135         case RENDERPATH_D3D10:
14136                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14137                 return;
14138         case RENDERPATH_D3D11:
14139                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14140                 return;
14141         }
14142
14143         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14144
14145 //      R_Mesh_ResetTextureState();
14146         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14147         GL_DepthRange(0, 1);
14148         GL_DepthTest(!r_showdisabledepthtest.integer);
14149         GL_DepthMask(false);
14150         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14151
14152         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14153         {
14154                 int triangleindex;
14155                 int bihleafindex;
14156                 qboolean cullbox = ent == r_refdef.scene.worldentity;
14157                 const q3mbrush_t *brush;
14158                 const bih_t *bih = &model->collision_bih;
14159                 const bih_leaf_t *bihleaf;
14160                 float vertex3f[3][3];
14161                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14162                 cullbox = false;
14163                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14164                 {
14165                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14166                                 continue;
14167                         switch (bihleaf->type)
14168                         {
14169                         case BIH_BRUSH:
14170                                 brush = model->brush.data_brushes + bihleaf->itemindex;
14171                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
14172                                 {
14173                                         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);
14174                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14175                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14176                                 }
14177                                 break;
14178                         case BIH_COLLISIONTRIANGLE:
14179                                 triangleindex = bihleaf->itemindex;
14180                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14181                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14182                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14183                                 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);
14184                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14185                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14186                                 break;
14187                         case BIH_RENDERTRIANGLE:
14188                                 triangleindex = bihleaf->itemindex;
14189                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14190                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14191                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14192                                 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);
14193                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14194                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14195                                 break;
14196                         }
14197                 }
14198         }
14199
14200         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14201
14202         if (r_showtris.integer || r_shownormals.integer)
14203         {
14204                 if (r_showdisabledepthtest.integer)
14205                 {
14206                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14207                         GL_DepthMask(false);
14208                 }
14209                 else
14210                 {
14211                         GL_BlendFunc(GL_ONE, GL_ZERO);
14212                         GL_DepthMask(true);
14213                 }
14214                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14215                 {
14216                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14217                                 continue;
14218                         rsurface.texture = R_GetCurrentTexture(surface->texture);
14219                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14220                         {
14221                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14222                                 if (r_showtris.value > 0)
14223                                 {
14224                                         if (!rsurface.texture->currentlayers->depthmask)
14225                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14226                                         else if (ent == r_refdef.scene.worldentity)
14227                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14228                                         else
14229                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14230                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14231                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14232                                         RSurf_DrawBatch();
14233                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14234                                         CHECKGLERROR
14235                                 }
14236                                 if (r_shownormals.value < 0)
14237                                 {
14238                                         qglBegin(GL_LINES);
14239                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14240                                         {
14241                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14242                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14243                                                 qglVertex3f(v[0], v[1], v[2]);
14244                                                 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14245                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14246                                                 qglVertex3f(v[0], v[1], v[2]);
14247                                         }
14248                                         qglEnd();
14249                                         CHECKGLERROR
14250                                 }
14251                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14252                                 {
14253                                         qglBegin(GL_LINES);
14254                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14255                                         {
14256                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14257                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14258                                                 qglVertex3f(v[0], v[1], v[2]);
14259                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14260                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14261                                                 qglVertex3f(v[0], v[1], v[2]);
14262                                         }
14263                                         qglEnd();
14264                                         CHECKGLERROR
14265                                         qglBegin(GL_LINES);
14266                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14267                                         {
14268                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14269                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14270                                                 qglVertex3f(v[0], v[1], v[2]);
14271                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14272                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14273                                                 qglVertex3f(v[0], v[1], v[2]);
14274                                         }
14275                                         qglEnd();
14276                                         CHECKGLERROR
14277                                         qglBegin(GL_LINES);
14278                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14279                                         {
14280                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14281                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14282                                                 qglVertex3f(v[0], v[1], v[2]);
14283                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14284                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14285                                                 qglVertex3f(v[0], v[1], v[2]);
14286                                         }
14287                                         qglEnd();
14288                                         CHECKGLERROR
14289                                 }
14290                         }
14291                 }
14292                 rsurface.texture = NULL;
14293         }
14294 }
14295
14296 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14297 int r_maxsurfacelist = 0;
14298 const msurface_t **r_surfacelist = NULL;
14299 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14300 {
14301         int i, j, endj, flagsmask;
14302         dp_model_t *model = r_refdef.scene.worldmodel;
14303         msurface_t *surfaces;
14304         unsigned char *update;
14305         int numsurfacelist = 0;
14306         if (model == NULL)
14307                 return;
14308
14309         if (r_maxsurfacelist < model->num_surfaces)
14310         {
14311                 r_maxsurfacelist = model->num_surfaces;
14312                 if (r_surfacelist)
14313                         Mem_Free((msurface_t**)r_surfacelist);
14314                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14315         }
14316
14317         RSurf_ActiveWorldEntity();
14318
14319         surfaces = model->data_surfaces;
14320         update = model->brushq1.lightmapupdateflags;
14321
14322         // update light styles on this submodel
14323         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14324         {
14325                 model_brush_lightstyleinfo_t *style;
14326                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14327                 {
14328                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14329                         {
14330                                 int *list = style->surfacelist;
14331                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14332                                 for (j = 0;j < style->numsurfaces;j++)
14333                                         update[list[j]] = true;
14334                         }
14335                 }
14336         }
14337
14338         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14339
14340         if (debug)
14341         {
14342                 R_DrawDebugModel();
14343                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14344                 return;
14345         }
14346
14347         rsurface.lightmaptexture = NULL;
14348         rsurface.deluxemaptexture = NULL;
14349         rsurface.uselightmaptexture = false;
14350         rsurface.texture = NULL;
14351         rsurface.rtlight = NULL;
14352         numsurfacelist = 0;
14353         // add visible surfaces to draw list
14354         for (i = 0;i < model->nummodelsurfaces;i++)
14355         {
14356                 j = model->sortedmodelsurfaces[i];
14357                 if (r_refdef.viewcache.world_surfacevisible[j])
14358                         r_surfacelist[numsurfacelist++] = surfaces + j;
14359         }
14360         // update lightmaps if needed
14361         if (model->brushq1.firstrender)
14362         {
14363                 model->brushq1.firstrender = false;
14364                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14365                         if (update[j])
14366                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14367         }
14368         else if (update)
14369         {
14370                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14371                         if (r_refdef.viewcache.world_surfacevisible[j])
14372                                 if (update[j])
14373                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14374         }
14375         // don't do anything if there were no surfaces
14376         if (!numsurfacelist)
14377         {
14378                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14379                 return;
14380         }
14381         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14382         GL_AlphaTest(false);
14383
14384         // add to stats if desired
14385         if (r_speeds.integer && !skysurfaces && !depthonly)
14386         {
14387                 r_refdef.stats.world_surfaces += numsurfacelist;
14388                 for (j = 0;j < numsurfacelist;j++)
14389                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14390         }
14391
14392         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14393 }
14394
14395 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14396 {
14397         int i, j, endj, flagsmask;
14398         dp_model_t *model = ent->model;
14399         msurface_t *surfaces;
14400         unsigned char *update;
14401         int numsurfacelist = 0;
14402         if (model == NULL)
14403                 return;
14404
14405         if (r_maxsurfacelist < model->num_surfaces)
14406         {
14407                 r_maxsurfacelist = model->num_surfaces;
14408                 if (r_surfacelist)
14409                         Mem_Free((msurface_t **)r_surfacelist);
14410                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14411         }
14412
14413         // if the model is static it doesn't matter what value we give for
14414         // wantnormals and wanttangents, so this logic uses only rules applicable
14415         // to a model, knowing that they are meaningless otherwise
14416         if (ent == r_refdef.scene.worldentity)
14417                 RSurf_ActiveWorldEntity();
14418         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14419                 RSurf_ActiveModelEntity(ent, false, false, false);
14420         else if (prepass)
14421                 RSurf_ActiveModelEntity(ent, true, true, true);
14422         else if (depthonly)
14423         {
14424                 switch (vid.renderpath)
14425                 {
14426                 case RENDERPATH_GL20:
14427                 case RENDERPATH_CGGL:
14428                 case RENDERPATH_D3D9:
14429                 case RENDERPATH_D3D10:
14430                 case RENDERPATH_D3D11:
14431                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14432                         break;
14433                 case RENDERPATH_GL13:
14434                 case RENDERPATH_GL11:
14435                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14436                         break;
14437                 }
14438         }
14439         else
14440         {
14441                 switch (vid.renderpath)
14442                 {
14443                 case RENDERPATH_GL20:
14444                 case RENDERPATH_CGGL:
14445                 case RENDERPATH_D3D9:
14446                 case RENDERPATH_D3D10:
14447                 case RENDERPATH_D3D11:
14448                         RSurf_ActiveModelEntity(ent, true, true, false);
14449                         break;
14450                 case RENDERPATH_GL13:
14451                 case RENDERPATH_GL11:
14452                         RSurf_ActiveModelEntity(ent, true, false, false);
14453                         break;
14454                 }
14455         }
14456
14457         surfaces = model->data_surfaces;
14458         update = model->brushq1.lightmapupdateflags;
14459
14460         // update light styles
14461         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14462         {
14463                 model_brush_lightstyleinfo_t *style;
14464                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14465                 {
14466                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14467                         {
14468                                 int *list = style->surfacelist;
14469                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14470                                 for (j = 0;j < style->numsurfaces;j++)
14471                                         update[list[j]] = true;
14472                         }
14473                 }
14474         }
14475
14476         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14477
14478         if (debug)
14479         {
14480                 R_DrawDebugModel();
14481                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14482                 return;
14483         }
14484
14485         rsurface.lightmaptexture = NULL;
14486         rsurface.deluxemaptexture = NULL;
14487         rsurface.uselightmaptexture = false;
14488         rsurface.texture = NULL;
14489         rsurface.rtlight = NULL;
14490         numsurfacelist = 0;
14491         // add visible surfaces to draw list
14492         for (i = 0;i < model->nummodelsurfaces;i++)
14493                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14494         // don't do anything if there were no surfaces
14495         if (!numsurfacelist)
14496         {
14497                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14498                 return;
14499         }
14500         // update lightmaps if needed
14501         if (update)
14502         {
14503                 int updated = 0;
14504                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14505                 {
14506                         if (update[j])
14507                         {
14508                                 updated++;
14509                                 R_BuildLightMap(ent, surfaces + j);
14510                         }
14511                 }
14512         }
14513         if (update)
14514                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14515                         if (update[j])
14516                                 R_BuildLightMap(ent, surfaces + j);
14517         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14518         GL_AlphaTest(false);
14519
14520         // add to stats if desired
14521         if (r_speeds.integer && !skysurfaces && !depthonly)
14522         {
14523                 r_refdef.stats.entities_surfaces += numsurfacelist;
14524                 for (j = 0;j < numsurfacelist;j++)
14525                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14526         }
14527
14528         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14529 }
14530
14531 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14532 {
14533         static texture_t texture;
14534         static msurface_t surface;
14535         const msurface_t *surfacelist = &surface;
14536
14537         // fake enough texture and surface state to render this geometry
14538
14539         texture.update_lastrenderframe = -1; // regenerate this texture
14540         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14541         texture.currentskinframe = skinframe;
14542         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14543         texture.offsetmapping = OFFSETMAPPING_OFF;
14544         texture.offsetscale = 1;
14545         texture.specularscalemod = 1;
14546         texture.specularpowermod = 1;
14547
14548         surface.texture = &texture;
14549         surface.num_triangles = numtriangles;
14550         surface.num_firsttriangle = firsttriangle;
14551         surface.num_vertices = numvertices;
14552         surface.num_firstvertex = firstvertex;
14553
14554         // now render it
14555         rsurface.texture = R_GetCurrentTexture(surface.texture);
14556         rsurface.lightmaptexture = NULL;
14557         rsurface.deluxemaptexture = NULL;
14558         rsurface.uselightmaptexture = false;
14559         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14560 }
14561
14562 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)
14563 {
14564         static msurface_t surface;
14565         const msurface_t *surfacelist = &surface;
14566
14567         // fake enough texture and surface state to render this geometry
14568         surface.texture = texture;
14569         surface.num_triangles = numtriangles;
14570         surface.num_firsttriangle = firsttriangle;
14571         surface.num_vertices = numvertices;
14572         surface.num_firstvertex = firstvertex;
14573
14574         // now render it
14575         rsurface.texture = R_GetCurrentTexture(surface.texture);
14576         rsurface.lightmaptexture = NULL;
14577         rsurface.deluxemaptexture = NULL;
14578         rsurface.uselightmaptexture = false;
14579         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14580 }